Может ли метод Java иметь более 255 локальных переменных?

Код операции iload Java используется для помещения значения из массива локальных переменных (LVA) в стек операндов.

Этот опкод принимает в качестве параметра один байт (en.wikipedia.org/wiki/Java_bytecode_instruction_listings), который служит индексом для LVA.

Если один элемент LVA всегда является ссылкой на объект (я думаю, это не относится к статическим методам, но давайте пока проигнорируем их), и если в качестве индекса используется ровно один байт (256 возможных значений), тогда как метод может иметь доступ к более чем 255 различным локальным переменным?


person corazza    schedule 24.12.2012    source источник
comment
Что происходит, когда вы пытаетесь это сделать?   -  person JB Nizet    schedule 25.12.2012


Ответы (2)


Да, методы Java могут иметь более 255 локальных переменных. Инструкцию wide можно использовать для изменения инструкции iload или aload для использования 16-битного индекса вместо 8-битного индекса, что означает, что вы можете иметь до 65536 различных локальных переменных в функции, пока код операции wide в итоге привыкает.

При этом обратите внимание, что локальные переменные Java не обязательно полностью соответствуют локальным переменным JVM. Возможно, компилятор Java может просмотреть ваш код, заметить, что пространство для локальных переменных может быть повторно использовано в некоторых контекстах, а затем сопоставить несколько локальных переменных Java с одними и теми же локальными переменными JVM.

Надеюсь это поможет!

person templatetypedef    schedule 24.12.2012
comment
Я не думаю, что (OpenJDK) javac делает это. Я подозреваю, что он также не использует wide. У меня на этой машине не установлена ​​Java, чтобы протестировать ее (и мне неинтересно смотреть код). - person Tom Hawtin - tackline; 25.12.2012
comment
@ TomHawtin-tackline- я не уверен, делает ли это какая-либо конкретная реализация javac, хотя в принципе это возможно (поскольку JVM поддерживает это). Если вы знаете какие-либо упоминания об этом, я хотел бы их увидеть. - person templatetypedef; 25.12.2012
comment
Кажется, что по крайней мере один компилятор действительно это делает - см. другой ответ. - person John Dvorak; 25.12.2012
comment
65536 переменных внутри одной функции — это предел, который недостижим, поскольку максимальный размер функции составляет 65535 байт. - person Jack Giffin; 06.01.2020

Я попробовал это для вас, написав программу с 300 локальными переменными. Этот фрагмент:

System.out.println(a255);
System.out.println(a256);

компилируется в это:

3575: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
3578: iload         255
3580: invokevirtual #53                 // Method java/io/PrintStream.println:(I)V
3583: getstatic     #16                 // Field java/lang/System.out:Ljava/io/PrintStream;
3586: iload_w       #256                // Utf8 a196
3590: invokevirtual #53                 // Method java/io/PrintStream.println:(I)V

Примечание: скомпилировано с помощью Eclipse и javac с точно такими же результатами.

person Marko Topolnik    schedule 24.12.2012
comment
Я имею в виду что-то вроде C4 15 01 00. iload_w #256 — это инструкция, а не код операции. - person John Dvorak; 25.12.2012
comment
Боюсь, javap этого не делает. Если ты знаешь способ, я сделаю это. - person Marko Topolnik; 25.12.2012
comment
Я так понимаю, вы не хотите открывать файл class в шестнадцатеричном редакторе? - person John Dvorak; 25.12.2012
comment
И просто сбросить все байты на вас? Как это тебе поможет? - person Marko Topolnik; 25.12.2012
comment
Конечно, есть еще en.wikipedia.org/wiki/Java_bytecode_instruction_listings , но мне нужен независимый источник для проверки. - person John Dvorak; 25.12.2012
comment
Вот эта повторяющаяся последовательность: c4 15 01 00 b6 00 35 b2 00 10 c4 15 01 01 b6 00 35 b2 00 10... и четвертый байт продолжает увеличиваться. - person Marko Topolnik; 25.12.2012
comment
Расшифровка из википедии: c4 15 xx xx =› wide iload xxxx; b6 00 35 =› invokevirtual #0x35; b2 00 10 =› getstatic #0x10 - person John Dvorak; 25.12.2012
comment
Википедия не подвела :) - person Marko Topolnik; 25.12.2012
comment
Кажется, что-то странное с приложением javap при использовании iload_w... javap показывает двухбайтовый индекс как ссылку на пул констант, тогда как на самом деле это должно быть просто iload_w 256, верно? Он также ссылается на то, что можно найти в # 256 в пуле констант, который является идентификатором для локальной переменной a196... не имеет смысла. - person fast-reflexes; 17.04.2014