Как работает bipush в JVM?

Я понимаю, что iload принимает целые числа от -1 до 5, но как вы можете расширить их до более высоких чисел с помощью инструкции bipush? Как конкретное целое число сохраняется с байт-кодом?


person Tim    schedule 04.05.2018    source источник
comment
Ваш вопрос очень неясен, спрашиваете ли вы о добавлении значений локальных переменных в стек, когда у вас есть более 4 локальных переменных на выбор (iload), или о добавлении литералов с помощью bipush.   -  person chrylis -cautiouslyoptimistic-    schedule 04.05.2018
comment
Я действительно спрашиваю об обоих. Iload_1 загружает целое число?   -  person Tim    schedule 04.05.2018
comment
iload_1 помещает int из локальной переменной №1 (второй, так как она начинается с нуля) в стек.   -  person chrylis -cautiouslyoptimistic-    schedule 04.05.2018
comment
Моя ошибка, я перепутал инструкции. Когда вы используете istore и храните более 4 переменных, как он обрабатывает размер? Я решил, что поле переменной - это фиксированный массив.   -  person Tim    schedule 04.05.2018
comment
Размер чего?   -  person chrylis -cautiouslyoptimistic-    schedule 05.05.2018
comment
Фиксированный размер переменного поля.   -  person Tim    schedule 05.05.2018
comment
Что такое переменное поле?   -  person chrylis -cautiouslyoptimistic-    schedule 05.05.2018
comment
Поле переменных - это то, как Hotspot VM хранит локальные переменные в каждом кадре.   -  person Tim    schedule 17.05.2018


Ответы (2)


Есть несколько разных инструкций, которые можно использовать для вставки целочисленной константы.

Самая маленькая - это инструкция iconst_ *. Это всего лишь один байт, потому что значение закодировано в самом коде операции. iconst_1, iconst_2 и т. д. - разные коды операций. iconst_5, например, будет закодирован как байт 08.

Примечание: iload - это совершенно не связанная инструкция, используемая для загрузки значения локальной переменной. Вы, должно быть, думали о iconst_ *.

Далее идет bipush, который может помещать константу между -128 и 127. Длина этой инструкции составляет два байта: первый байт - это код операции, а второй байт - это 8-битное целое число со знаком. Вы даже можете использовать его для передачи констант в диапазоне от -1 до 5, хотя это займет больше места в файле классов, чем необходимо. Например, bipush 5 будет закодирован как 10 05. (0x10 - код операции для bipush)

Далее идет sipush, который является таким же, за исключением того, что он хранит 16-битную константу вместо 8-битной константы, и, следовательно, длина инструкции составляет три байта. Код операции для sipush - 0x11, поэтому sipush 5 будет закодирован как трехбайтовая последовательность 11 00 05.

Вы можете задаться вопросом, как хранятся целочисленные константы, не умещающиеся в 16 битах. В этом случае компилятор создает записи в отдельном разделе файла классов, называемом пулом констант, а затем использует инструкцию ldc или ldc_w для ссылки на запись пула констант.

person Antimony    schedule 04.05.2018
comment
Итак, как байт-код реализован в интерпретаторе, если он содержит инструкцию и значение? Я думал, что каждый байт-код - это int8_t. - person Tim; 04.05.2018
comment
@Tim Каждый код операции - это один байт. В зависимости от их определений, за операциями могут следовать операнды. - person chrylis -cautiouslyoptimistic-; 04.05.2018
comment
Поскольку это один байт, как могут быть два значения, целое число и инструкция двупуша? - person Tim; 04.05.2018
comment
Какой общий компонент в интерпретаторе JVM представляет собой целочисленный аргумент? - person Tim; 05.05.2018

Я думаю, вы ищете раздел 2.11 JVMS, который касается представления инструкций. В частности, он использует очевидный порядок: код операции, сразу за которым следуют операнды по порядку, с прямым порядком байтов (как и все представления Java). В случае bipush это будет байт 0x10, за которым следует буквальное значение.

person chrylis -cautiouslyoptimistic-    schedule 04.05.2018