Spec-Zone.ru › Java Virtual Machine Specification 17

Глава 6. Набор инструкций виртуальной машины Java

Оглавление

6.1. Предположения: Что означает «должен»
6.2. Зарезервированные опкоды
6.3. Ошибки виртуальной машины
6.4. Формат описаний инструкций
мнемоника
6.5. Инструкции
aaload
aastore
aconst_null
aload
aload_
anewarray
areturn
arraylength
astore
astore_
athrow
baload
bastore
bipush
caload
castore
checkcast
d2f
d2i
d2l
dadd
daload
dastore
dcmp<op>
dconst_
ddiv
dload
dload_
dmul
dneg
drem
dreturn
dstore
dstore_
dsub
dup
dup_x1
dup_x2
dup2
dup2_x1
dup2_x2
f2d
f2i
f2l
fadd
faload
fastore
fcmp<op>
fconst_
fdiv
fload
fload_
fmul
fneg
frem
freturn
fstore
fstore_
fsub
getfield
getstatic
goto
goto_w
i2b
i2c
i2d
i2f
i2l
i2s
iadd
iaload
iand
iastore
iconst_
idiv
if_acmp<cond>
if_icmp<cond>
if<cond>
ifnonnull
ifnull
iinc
iload
iload_
imul
ineg
instanceof
invokedynamic
invokeinterface
invokespecial
invokestatic
invokevirtual
ior
irem
ireturn
ishl
ishr
istore
END_OF_DOCUMENT_MARKER
istore_
isub
iushr
ixor
jsr
jsr_w
l2d
l2f
l2i
ladd
laload
land
lastore
lcmp
lconst_
ldc
ldc_w
ldc2_w
ldiv
lload
lload_
lmul
lneg
lookupswitch
lor
lrem
lreturn
lshl
lshr
lstore
lstore_
lsub
lushr
lxor
monitorenter
monitorexit
multianewarray
new
newarray
nop
pop
pop2
putfield
putstatic
ret
return
saload
sastore
sipush
swap
tableswitch
wide

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

6.1. Допущения: Значение "должен"

Описание каждой инструкции всегда даётся в контексте кода виртуальной машины Java, удовлетворяющего статическим и структурным ограничениям §4 (Формат файла class). В описании отдельных инструкций виртуальной машины Java часто утверждается, что некоторая ситуация "должна" или "не должна" быть: "Значение value2 должно быть типа int". Ограничения §4 (Формат файла class) гарантируют, что все такие ожидания будут на самом деле выполнены. Если при выполнении некоторое ограничение (в виде "должен" или "не должен") в описании инструкции не выполняется, поведение виртуальной машины Java неопределено.

Виртуальная машина Java проверяет, удовлетворяет ли код виртуальной машины Java статическим и структурным ограничениям во время компоновки, используя верификатор файлов class (§4.10). Таким образом, виртуальная машина Java будет пытаться выполнить код только из действительных файлов class.

Выполнение проверки во время компоновки предпочтительно, так как проверки выполняются только один раз, что существенно уменьшает объём работы, которую необходимо выполнить во время выполнения. Другие стратегии реализации возможны, при условии, что они соответствуют Спецификации языка Java, издание Java SE 17 и Спецификации виртуальной машины Java, издание Java SE 17.

6.2. Зарезервированные коды операций

В дополнение к кодам операций инструкций, указанных позже в этом разделе, которые используются в файлах class (§4 (Формат файла class)), три кода операций зарезервированы для внутреннего использования реализацией виртуальной машины Java.

Два из зарезервированных кодов операций, номера 254 (0xfe) и 255 (0xff), имеют мнемоники impdep1 и impdep2 соответственно. Эти инструкции предназначены для предоставления «задних дверей» или ловушек для реализации специфичных для реализации функций, реализованных в программном и аппаратном обеспечении соответственно.

Третий зарезервированный код операции, номер 202 (0xca), имеет мнемонику breakpoint и предназначен для использования отладчиками для реализации точек останова.

Несмотря на то, что эти коды операций были зарезервированы, они могут использоваться только внутри реализации виртуальной машины Java. Они не могут появляться в допустимых файлах class. Инструменты, такие как отладчики или генераторы JIT-кода (§2.13), которые могут напрямую взаимодействовать с кодом виртуальной машины Java, который уже загружен и выполняется, могут столкнуться с этими кодами операций. Такие инструменты должны стараться вести себя корректно, если они сталкиваются с любой из этих зарезервированных инструкций.

6.3. Ошибки виртуальной машины

Реализация Java виртуальной машины выбрасывает объект, являющийся экземпляром подкласса класса VirtualMachineError, когда внутренняя ошибка или ограничение ресурсов препятствуют ей в реализации семантики, описанной в этой главе. Данный документ не может предсказать, где могут возникнуть внутренние ошибки или ограничения ресурсов, и не предписывает точное время их сообщения. Таким образом, любой из подклассов VirtualMachineError, определенных ниже, может быть сгенерирован в любое время во время работы Java виртуальной машины:

  • InternalError: В реализации Java виртуальной машины произошла внутренняя ошибка из-за сбоя в программном обеспечении, реализующем виртуальную машину, сбоя в программном обеспечении базовой хост-системы или сбоя в аппаратном обеспечении. Эта ошибка передается асинхронно (§2.10) при обнаружении и может возникнуть в любой точке программы.

  • OutOfMemoryError: Реализация Java виртуальной машины исчерпала виртуальную или физическую память, и автоматический менеджер памяти не смог вернуть достаточно памяти для удовлетворения запроса на создание объекта.

  • StackOverflowError: Реализация Java виртуальной машины исчерпала стек памяти для потока, обычно потому, что поток выполняет неограниченное количество рекурсивных вызовов в результате сбоя в выполняемой программе.

  • UnknownError: Произошла ошибка или исключение, но реализация Java виртуальной машины не может сообщить об actual исключении или ошибке.

6.4. Формат описаний инструкций

Инструкции Java виртуальной машины представлены в этой главе записями следующего вида, в алфавитном порядке и на новой странице для каждой записи.

мнемоника

Операция

Краткое описание инструкции

Формат


мнемоника
операнд1
операнд2
...

Формы

мнемоника = код операции

Стек операндов

..., значение1, значение2 →

..., значение3

Описание

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

Исключения при связывании

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

Исключения во время выполнения

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

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

Примечания

Комментарии, которые не являются строго частью спецификации инструкции, выводятся как примечания в конце описания.

Каждая ячейка в диаграмме формата инструкции представляет собой один 8-битовый байт. Мемоника инструкции — это ее имя. Ее код операции — ее числовое представление, приведенное в десятичном и шестнадцатеричном форматах. Только числовое представление фактически присутствует в коде Java виртуальной машины в файле class.

Обратите внимание, что существуют «операнды», генерируемые во время компиляции и встроенные в инструкции Java виртуальной машины, а также «операнды», вычисляемые во время выполнения и предоставляемые в стеке операндов. Несмотря на то, что они поступают из разных источников, все эти операнды представляют собой одно и то же: значения, над которыми будет выполняться инструкция Java виртуальной машины. Используя неявное получение многих операндов из стека операндов, а не их явное представление в скомпилированном коде в виде дополнительных байтов операндов, номеров регистров и т. д., код Java виртуальной машины остается компактным.

Некоторые инструкции представлены как члены семейства родственных инструкций, имеющих общее описание, формат и диаграмму стека операндов. Как таковое, семейство инструкций включает несколько кодов операций и мнемоник; в диаграмме формата инструкции появляется только мнемоника семейства, а отдельный ряд форм перечисляет все мнемоники и коды операций членов. Например, строка Формы для семейства инструкций lconst_<l>, дающая информацию о мнемонике и коде операции для двух инструкций в этом семействе (lconst_0 и lconst_1), выглядит следующим образом:

lconst_0 = 9 (0x9)

lconst_1 = 10 (0xa)

В описании инструкций Java виртуальной машины воздействие выполнения инструкции на стек операндов (§2.6.2) текущей фрейма (§2.6) представлено текстово, со стеком, возрастающим слева направо, и каждым значением, представленным отдельно. Таким образом,

..., значение1, значение2 →

..., результат

показывает операцию, которая начинается с значение2 на вершине стека операндов, а значение1 непосредственно под ним. В результате выполнения инструкции значение1 и значение2 извлекаются из стека операндов и заменяются значением результат, которое было вычислено инструкцией. Остальная часть стека операндов, представленная многоточием (...), не затрагивается выполнением инструкции.

Значения типов long и double представлены одной записью в стеке операндов.

В первом издании спецификации Java® виртуальной машины значения в стеке операндов типов long и double в диаграмме стека представлялись двумя записями.

6.5. Инструкции

aaload

Операция

Загрузка reference из массива

Формат


aaload

Формы

aaload = 50 (0x32)

Стек операндов

..., arrayref, index →

..., value

Описание

arrayref должен иметь тип reference и должен ссылаться на массив, компоненты которого имеют тип reference. index должен иметь тип int. Оба arrayref и index извлекаются из стека операндов. Значение value компонента массива по индексу index извлекается и помещается в стек операндов.

Исключения во время выполнения

Если arrayref является null, aaload вызывает исключение NullPointerException.

В противном случае, если index выходит за пределы массива, на который ссылается arrayref, инструкция aaload вызывает исключение ArrayIndexOutOfBoundsException.

aastore

Операция

Запись в массив reference

Формат


aastore

Формы

aastore = 83 (0x53)

Стек операндов

..., arrayref, index, value →

...

Описание

arrayref должен иметь тип reference и должен ссылаться на массив, компоненты которого имеют тип reference. index должен иметь тип int, а value должен иметь тип reference. arrayref, index и value извлекаются из стека операндов.

Если value является null, то value сохраняется как компонент массива по индексу index.

В противном случае, value не является null. Если тип value совместим с типом компонентов массива, на который ссылается arrayref, то value сохраняется как компонент массива по индексу index.

Следующие правила используются для определения того, является ли value, которое не является null, совместимым с типом компонента массива. Если S — тип объекта, на который ссылается value, а T — тип ссылки компонентов массива, то aastore определяет совместимость присваивания следующим образом:

  • Если S — тип класса, то:

    • Если T — тип класса, то S должен быть тем же классом, что и T, или S должен быть подклассом T;

    • Если T — тип интерфейса, то S должен реализовывать интерфейс T.

  • Если S — тип массива SC[], то есть массив компонентов типа SC, то:

    • Если T — тип класса, то T должен быть Object.

    • Если T — тип интерфейса, то T должен быть одним из интерфейсов, реализуемых массивами (JLS §4.10.3).

    • Если T — тип массива TC[], то есть массив компонентов типа TC, то одно из следующих утверждений должно быть истинным:

      • TC и SC — один и тот же примитивный тип.

      • TC и SC — типы ссылок, и тип SC присваивается TC по этим правилам выполнения.

Исключения во время выполнения

Если arrayref является null, aastore вызывает исключение NullPointerException.

В противном случае, если index выходит за пределы массива, на который ссылается arrayref, инструкция aastore вызывает исключение ArrayIndexOutOfBoundsException.

В противном случае, если arrayref не является null и фактический тип не-null value не совместим с фактическим типом компонентов массива, aastore вызывает исключение ArrayStoreException.

aconst_null

Операция

Помещение null

Формат


aconst_null

Формы

aconst_null = 1 (0x1)

Стек операндов

... →

..., null

Описание

Помещение объекта null reference в стек операндов.

Примечания

Виртуальная машина Java не предписывает конкретное значение для null.

aload

Операция

Загрузка reference из локальной переменной

Формат


aload
index

Формы

aload = 25 (0x19)

Стек операндов

... →

..., objectref

Описание

Значение index — это беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу index должна содержать reference. Объект objectref из локальной переменной по индексу index помещается на стек операндов.

Примечания

Инструкция aload не может быть использована для загрузки значения типа returnAddress из локальной переменной на стек операндов. Эта асимметрия с инструкцией astore (§astore) является умышленной.

Операция aload может использоваться в сочетании с инструкцией wide (§wide) для доступа к локальной переменной, используя двухбайтовый беззнаковый индекс.

aload_<n>

Операция

Загрузка reference из локальной переменной

Формат


aload_<n>

Формы

aload_0 = 42 (0x2a)

aload_1 = 43 (0x2b)

aload_2 = 44 (0x2c)

aload_3 = 45 (0x2d)

Стек операндов

... →

..., objectref

Описание

Значение <n> должно быть индексом в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу <n> должна содержать reference. Объект objectref из локальной переменной по индексу <n> помещается на стек операндов.

Примечания

Инструкция aload_<n> не может быть использована для загрузки значения типа returnAddress из локальной переменной на стек операндов. Эта асимметрия с соответствующей инструкцией astore_<n> (§astore_<n>) является умышленной.

Каждая из инструкций aload_<n> аналогична aload с индексом <n>, за исключением того, что операнд <n> неявный.

anewarray

Операция

Создание нового массива reference

Формат


anewarray
indexbyte1
indexbyte2

Формы

anewarray = 189 (0xbd)

Стек операндов

..., count →

..., arrayref

Описание

Значение count должно быть типа int. Оно извлекается со стека операндов. count представляет количество компонентов создаваемого массива. Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле констант времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула констант времени выполнения по этому индексу должен быть символической ссылкой на тип класса, массива или интерфейса. Указанный тип класса, массива или интерфейса разрешается (§5.4.3.1). Создается новый массив с компонентами этого типа, длиной count, выделенный в куче сборки мусора, и ссылка arrayref на этот новый объект массива помещается на стек операндов. Все компоненты нового массива инициализируются значением по умолчанию для типов reference (§2.4).

Исключения при связывании

При разрешении символической ссылки на тип класса, массива или интерфейса могут быть выброшены любые исключения, описанные в §5.4.3.1.

Исключения времени выполнения

В противном случае, если count меньше нуля, инструкция anewarray генерирует исключение NegativeArraySizeException.

Примечания

Инструкция anewarray используется для создания одномерного массива ссылок на объекты или части многомерного массива.

areturn

Операция

Возврат reference из метода

Формат


areturn

Формы

areturn = 176 (0xb0)

Стек операндов

..., objectref →

[пустой]

Описание

objectref должен быть типа reference и должен ссылаться на объект типа, совместимого с типом, представленным дескриптором возврата (§4.3.3) текущего метода. Если текущий метод является методом synchronized, монитор, захваченный или повторно захваченный при вызове метода, обновляется и, возможно, выходит, как если бы выполнялась инструкция monitorexit (§monitorexit) в текущем потоке. Если исключение не генерируется, objectref извлекается из стека операндов текущей рамки (§2.6) и помещается в стек операндов рамки вызывающего метода. Все остальные значения в стеке операндов текущего метода удаляются.

Затем интерпретатор восстанавливает рамку вызывающего метода и возвращает управление вызывающему методу.

Исключения во время выполнения

Если реализация Java Virtual Machine не выполняет правила структурированной блокировки, описанные в §2.11.10, то если текущий метод является методом synchronized, а текущий поток не является владельцем монитора, захваченного или повторно захваченного при вызове метода, то areturn генерирует исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит инструкцию monitorexit, но не инструкцию monitorenter, для объекта, на котором синхронизирован метод.

В противном случае, если реализация Java Virtual Machine выполняет правила структурированной блокировки, описанные в §2.11.10, и если первое из этих правил нарушается во время вызова текущего метода, то areturn генерирует исключение IllegalMonitorStateException.

arraylength

Операция

Получение длины массива

Формат


arraylength

Формы

arraylength = 190 (0xbe)

Стек операндов

..., arrayref →

..., length

Описание

arrayref должен быть типа reference и должен ссылаться на массив. Он извлекается из стека операндов. Определяется длина length массива, на который он ссылается. Эта длина length помещается в стек операндов как int.

Исключения во время выполнения

Если arrayref является null, инструкция arraylength генерирует исключение NullPointerException.

astore

Операция

Сохранение reference в локальную переменную

Формат


astore
index

Формы

astore = 58 (0x3a)

Стек операндов

..., objectref →

...

Описание

index — это беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей рамки (§2.6). objectref вверху стека операндов должен быть типа returnAddress или типа reference. Он извлекается из стека операндов, и значение локальной переменной по индексу index устанавливается в objectref.

Примечания

Инструкция astore используется с objectref типа returnAddress при реализации фрагмента finally языка программирования Java (§3.13).

Инструкция aload (§aload) не может использоваться для загрузки значения типа returnAddress из локальной переменной в стек операндов. Эта асимметрия с инструкцией astore является намеренной.

Код операции astore может использоваться совместно с инструкцией wide (§wide), чтобы получить доступ к локальной переменной, используя двубайтовый беззнаковый индекс.

END_OF_DOCUMENT_MARKER

astore_<n>

Операция

Сохранение reference в локальной переменной

Формат


astore_<n>

Формы

astore_0 = 75 (0x4b)

astore_1 = 76 (0x4c)

astore_2 = 77 (0x4d)

astore_3 = 78 (0x4e)

Стек операндов

..., objectref →

...

Описание

<n> должно быть индексом в массиве локальных переменных текущей рамки (§2.6). objectref вверху стека операндов должен быть типа returnAddress или типа reference. Он извлекается из стека операндов, и значение локальной переменной в <n> устанавливается в objectref.

Примечания

Инструкции astore_<n> используются с objectref типа returnAddress при реализации положений языка программирования Java (§3.13).

Инструкция aload_<n> (§aload_<n>) не может быть использована для загрузки значения типа returnAddress из локальной переменной в стек операндов. Эта асимметрия с соответствующей инструкцией astore_<n> намеренная.

Каждая из инструкций astore_<n> аналогична инструкции astore с index <n>, за исключением того, что операнд <n> неявный.

athrow

Операция

Выброс исключения или ошибки

Формат


athrow

Формы

athrow = 191 (0xbf)

Стек операндов

..., objectref →

objectref

Описание

objectref должен быть типа reference и должен ссылаться на объект, являющийся экземпляром класса Throwable или подкласса Throwable. Он извлекается из стека операндов. objectref затем выбрасывается, выполняя поиск в текущем методе (§2.6) первого обработчика исключений, соответствующего классу objectref, как задано алгоритмом в §2.10.

Если обработчик исключений, соответствующий objectref, найден, он содержит местоположение кода, предназначенного для обработки этого исключения. Регистр pc сбрасывается до этого местоположения, стек операндов текущей рамки очищается, objectref заново помещается в стек операндов, и выполнение продолжается.

Если соответствующий обработчик исключений не найден в текущей рамке, эта рамка извлекается. Если текущая рамка представляет вызов метода synchronized, монитор, вошедший или повторно вошедший во время вызова метода, выходит, как если бы была выполнена инструкция monitorexit (§monitorexit). Наконец, рамка вызывающего метода, если она существует, восстанавливается, и objectref повторно выбрасывается. Если такой рамки нет, текущий поток завершается.

Исключения во время выполнения

Если objectref null, athrow выбрасывает NullPointerException вместо objectref.

В противном случае, если реализация Java Virtual Machine не применяет правила структурированного блокирования, описанные в §2.11.10, то если метод текущей рамки является методом synchronized, и текущий поток не является владельцем монитора, вошедшего или повторно вошедшего во время вызова метода, athrow выбрасывает IllegalMonitorStateException вместо объекта, ранее подлежащего выбросу. Это может произойти, например, если метод synchronized, прерывающий выполнение, содержит инструкцию monitorexit, но не инструкцию monitorenter, на объекте, на котором синхронизирован метод.

В противном случае, если реализация Java Virtual Machine применяет правила структурированного блокирования, описанные в §2.11.10, и если первое из этих правил нарушено во время вызова текущего метода, то athrow выбрасывает IllegalMonitorStateException вместо объекта, ранее подлежащего выбросу.

Примечания

Диаграмма стека операндов для инструкции athrow может быть вводящей в заблуждение: Если обработчик этого исключения соответствует в текущем методе, инструкция athrow отбрасывает все значения в стеке операндов, а затем помещает выброшенный объект в стек операндов. Однако, если обработчик не найден в текущем методе и исключение выбрасывается выше по цепочке вызова методов, то стек операндов метода (если есть), который обрабатывает исключение, очищается, и objectref помещается в этот пустой стек операндов. Все промежуточные рамки от метода, который сбросил исключение до, но не включая, метод, который обрабатывает исключение, отбрасываются.

baload

Операция

Загрузка из массива типа byte или boolean

Формат


baload

Формы

baload = 51 (0x33)

Стек операндов

..., arrayref, index →

..., value

Описание

arrayref должен быть типа reference и ссылаться на массив, компоненты которого являются типа byte или типа boolean. index должен быть типа int. Оба arrayref и index извлекаются со стека операндов. Значение value компонента массива по индексу index извлекается, расширяется со знаком до значения типа int и помещается на вершину стека операндов.

Исключения во время выполнения

Если arrayref имеет значение null, инструкция baload генерирует исключение NullPointerException.

В противном случае, если index выходит за пределы границ массива, к которому ссылается arrayref, инструкция baload генерирует исключение ArrayIndexOutOfBoundsException.

Примечания

Инструкция baload используется для загрузки значений из массивов byte и boolean. В реализации Oracle's Java Virtual Machine, массивы boolean, то есть массивы типа T_BOOLEAN (§2.2, §newarray), реализованы как массивы 8-битовых значений. Другие реализации могут реализовывать упакованные массивы boolean; инструкция baload таких реализаций должна использоваться для доступа к этим массивам.

bastore

Операция

Сохранение в массив типа byte или boolean

Формат


bastore

Формы

bastore = 84 (0x54)

Стек операндов

..., arrayref, index, value →

...

Описание

arrayref должен быть типа reference и ссылаться на массив, компоненты которого являются типа byte или типа boolean. index и value должны быть типа int. Значения arrayref, index и value извлекаются со стека операндов.

Если arrayref ссылается на массив, компоненты которого являются типа byte, то значение value усекается до типа byte и сохраняется как компонент массива по индексу index.

Если arrayref ссылается на массив, компоненты которого являются типа boolean, то значение value сужается, взяв побитовое И от value и 1; результат сохраняется как компонент массива по индексу index.

Исключения во время выполнения

Если arrayref имеет значение null, инструкция bastore генерирует исключение NullPointerException.

В противном случае, если index выходит за пределы границ массива, к которому ссылается arrayref, инструкция bastore генерирует исключение ArrayIndexOutOfBoundsException.

Примечания

Инструкция bastore используется для сохранения значений в массивы byte и boolean. В реализации Oracle's Java Virtual Machine, массивы boolean, то есть массивы типа T_BOOLEAN (§2.2, §newarray), реализованы как массивы 8-битовых значений. Другие реализации могут реализовывать упакованные массивы boolean; в таких реализациях инструкция bastore должна уметь сохранять значения типа boolean в упакованные массивы boolean, а также значения типа byte в массивы типа byte.

bipush

Операция

Поместить byte

Формат


bipush
byte

Формы

bipush = 16 (0x10)

Стек операндов

... →

..., value

Описание

Непосредственное значение byte расширяется со знаком до значения типа int. Это значение value помещается на стек операндов.

caload

Операция

Загрузка из массива

Формат


caload

Формы

caload = 52 (0x34)

Стек операндов

..., arrayref, index →

..., value

Описание

arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип char. index должен быть типа int. Оба arrayref и index извлекаются из стека операндов. Компонент массива по индексу index извлекается и расширяется до нуля до типа int value. Этот value помещается в стек операндов.

Исключения во время выполнения

Если arrayref является null, caload выбрасывает исключение NullPointerException.

В противном случае, если index не находится в пределах границ массива, на который ссылается arrayref, инструкция caload выбрасывает исключение ArrayIndexOutOfBoundsException.

castore

Операция

Запись в массив

Формат


castore

Формы

castore = 85 (0x55)

Стек операндов

..., arrayref, index, value →

...

Описание

arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип char. index и value должны быть типа int. arrayref, index и value извлекаются из стека операндов. Значение value преобразуется к типу char и сохраняется в качестве компонента массива по индексу index.

Исключения во время выполнения

Если arrayref является null, castore выбрасывает исключение NullPointerException.

В противном случае, если index не находится в пределах границ массива, на который ссылается arrayref, инструкция castore выбрасывает исключение ArrayIndexOutOfBoundsException.

checkcast

Операция

Проверка, является ли объект заданного типа

Формат


checkcast
indexbyte1
indexbyte2

Формы

checkcast = 192 (0xc0)

Стек операндов

..., objectref →

..., objectref

Описание

objectref должен быть типа reference. Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения по данному индексу должен быть символической ссылкой на тип класса, массива или интерфейса.

Если objectref является null, то стек операндов не изменяется.

В противном случае, указанный тип класса, массива или интерфейса разрешается (§5.4.3.1). Если objectref может быть приведён к типу разрешённого класса, массива или интерфейса, стек операндов не изменяется; в противном случае инструкция checkcast генерирует исключение ClassCastException.

Следующие правила используются для определения возможности приведения objectref, который не является null, к разрешённому типу. Если S — тип объекта, на который ссылается objectref, а T — разрешённый тип класса, массива или интерфейса, то checkcast определяет возможность приведения objectref к типу T следующим образом:

  • Если S — тип класса, то:

    • Если T — тип класса, то S должен быть тем же классом, что и T, или S должен быть подклассом T;

    • Если T — тип интерфейса, то S должен реализовывать интерфейс T.

  • Если S — тип массива SC[], то есть массив компонентов типа SC, то:

    • Если T — тип класса, то T должен быть Object.

    • Если T — тип интерфейса, то T должен быть одним из интерфейсов, реализуемых массивами (JLS §4.10.3).

    • Если T — тип массива TC[], то есть массив компонентов типа TC, то одно из следующих утверждений должно быть истинным:

      • TC и SC являются одним и тем же примитивным типом.

      • TC и SC являются ссылочными типами, и тип SC может быть приведён к TC путём рекурсивного применения этих правил.

Исключения при связывании

Во время разрешения символической ссылки на тип класса, массива или интерфейса могут быть сгенерированы любые исключения, описанные в §5.4.3.1.

Исключение времени выполнения

В противном случае, если objectref не может быть приведён к разрешённому классу, массиву или типу интерфейса, инструкция checkcast генерирует исключение ClassCastException.

Примечания

Инструкция checkcast очень похожа на инструкцию instanceof (§instanceof). Они отличаются по обработке null, поведению при неудачном тесте (checkcast генерирует исключение, instanceof помещает результат в стек), и по своему воздействию на стек операндов.

d2f

Операция

Преобразование double в float

Формат


d2f

Формы

d2f = 144 (0x90)

Стек операндов

..., value →

..., result

Описание

value вверху стека операндов должен быть типа double. Он извлекается из стека операндов и преобразуется в float result с помощью политики округления до ближайшего значения (§2.8). result помещается в стек операндов.

Конечное value, слишком маленькое для представления в виде float, преобразуется в ноль с тем же знаком; конечное value, слишком большое для представления в виде float, преобразуется в бесконечность с тем же знаком. double NaN преобразуется в float NaN.

Примечания

Инструкция d2f выполняет сужающее преобразование примитивных типов (JLS §5.1.3). Она может потерять информацию об общем значении value и может также потерять точность.

d2i

Операция

Преобразовать double в int

Формат


d2i

Формы

d2i = 142 (0x8e)

Стек операндов

..., значение →

..., результат

Описание

Значение значение на вершине стека операндов должно быть типа double. Оно извлекается из стека операндов и преобразуется в целочисленное значение результат. Результат помещается в стек операндов:

  • Если значение равно NaN, результат преобразования — целое число 0.

  • В противном случае, если значение не бесконечно, оно округляется до целого значения V с применением правила округления к нулю (§2.8). Если это целое значение V может быть представлено как int, то результат — значение V типа int.

  • В противном случае, либо значение слишком мало (отрицательное значение большой величины или отрицательная бесконечность), и результатом является наименьшее представимое значение типа int, либо значение слишком велико (положительное значение большой величины или положительная бесконечность), и результатом является наибольшее представимое значение типа int.

Примечания

Инструкция d2i выполняет сужение примитивного преобразования (JLS §5.1.3). Она может потерять информацию о величине значение и может также потерять точность.

d2l

Операция

Преобразовать double в long

Формат


d2l

Формы

d2l = 143 (0x8f)

Стек операндов

..., значение →

..., результат

Описание

Значение значение на вершине стека операндов должно быть типа double. Оно извлекается из стека операндов и преобразуется в целое значение результат. Результат помещается в стек операндов:

  • Если значение равно NaN, результат преобразования — целое число 0.

  • В противном случае, если значение не бесконечно, оно округляется до целого значения V с применением правила округления к нулю (§2.8). Если это целое значение V может быть представлено как long, то результат — значение V типа long.

  • В противном случае, либо значение слишком мало (отрицательное значение большой величины или отрицательная бесконечность), и результатом является наименьшее представимое значение типа long, либо значение слишком велико (положительное значение большой величины или положительная бесконечность), и результатом является наибольшее представимое значение типа long.

Примечания

Инструкция d2l выполняет сужение примитивного преобразования (JLS §5.1.3). Она может потерять информацию о величине значение и может также потерять точность.

dadd

Операция

Сложить double

Формат


dadd

Формы

dadd = 99 (0x63)

Стек операндов

..., значение1, значение2 →

..., результат

Описание

Оба значение1 и значение2 должны быть типа double. Значения извлекаются из стека операндов. Результат результат — значение1 + значение2. Результат помещается в стек операндов.

Результат инструкции dadd определяется правилами арифметики IEEE 754:

  • Если либо значение1, либо значение2 равно NaN, результат — NaN.

  • Сумма двух бесконечностей с разными знаками — NaN.

  • Сумма двух бесконечностей с одинаковыми знаками — бесконечность с таким же знаком.

  • Сумма бесконечности и любого конечного значения равна бесконечности.

  • Сумма двух нулей с разными знаками — положительный ноль.

  • Сумма двух нулей с одинаковыми знаками — ноль с таким же знаком.

  • Сумма нуля и ненулевого конечного значения равна ненулевому значению.

  • Сумма двух ненулевых конечных значений с одинаковой величиной и разными знаками — положительный ноль.

  • В остальных случаях, когда ни один из операндов не является бесконечностью, нулём или NaN, и значения имеют одинаковый знак или разные величины, сумма вычисляется и округляется до ближайшего представимого значения с применением правила округления к ближайшему (§2.8). Если величина слишком велика для представления как double, то говорят, что произошёл переполнение; результат — бесконечность с соответствующим знаком. Если величина слишком мала для представления как double, то говорят, что произошёл недолив; результат — ноль с соответствующим знаком.

Виртуальная машина Java требует поддержки постепенного недолива. Несмотря на то, что переполнение, недолив или потеря точности могут произойти, выполнение инструкции dadd никогда не вызывает исключения выполнения.

daload

Операция

Загрузка из массива double

Формат


daload

Формы

daload = 49 (0x31)

Стек операндов

..., arrayref, index →

..., value

Описание

arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип double. index должен быть типа int. Оба arrayref и index извлекаются из стека операндов. Значение value в компоненте массива по индексу index извлекается и помещается в стек операндов.

Исключения во время выполнения

Если arrayref является null, daload выбрасывает исключение NullPointerException.

В противном случае, если index выходит за пределы массива, на который ссылается arrayref, инструкция daload выбрасывает исключение ArrayIndexOutOfBoundsException.

dastore

Операция

Сохранение в массив double

Формат


dastore

Формы

dastore = 82 (0x52)

Стек операндов

..., arrayref, index, value →

...

Описание

arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип double. index должен быть типа int, а значение — типа double. arrayref, index и value извлекаются из стека операндов. Значение value сохраняется как компонент массива с индексом index.

Исключения во время выполнения

Если arrayref является null, dastore выбрасывает исключение NullPointerException.

В противном случае, если index выходит за пределы массива, на который ссылается arrayref, инструкция dastore выбрасывает исключение ArrayIndexOutOfBoundsException.

dcmp<op>

Операция

Сравнение double

Формат


dcmp<op>

Формы

dcmpg = 152 (0x98)

dcmpl = 151 (0x97)

Стек операндов

..., value1, value2 →

..., result

Описание

value1 и value2 должны быть типа double. Значения извлекаются из стека операндов и выполняется сравнение с плавающей запятой:

  • Если value1 больше value2, на стек операндов помещается значение 1.

  • В противном случае, если value1 равно value2, на стек операндов помещается значение 0.

  • В противном случае, если value1 меньше value2, на стек операндов помещается значение -1.

  • В противном случае, по крайней мере одно из value1 или value2 является NaN. Инструкция dcmpg помещает на стек операндов значение 1, а инструкция dcmpl помещает значение -1.

Сравнение с плавающей запятой выполняется в соответствии со спецификацией IEEE 754. Все значения, кроме NaN, упорядочены, причём отрицательная бесконечность меньше всех конечных значений, а положительная бесконечность больше всех конечных значений. Положительный и отрицательный нули считаются равными.

Примечания

Инструкции dcmpg и dcmpl отличаются только обработкой сравнения с участием NaN. NaN неупорядочен, поэтому любое сравнение не выполнится, если один или оба операнда равны NaN. Наличие dcmpg и dcmpl позволяет при любом сравнении получить одинаковый результат в стеке операндов, как при неудаче сравнения на значениях, отличных от NaN, так и при обнаружении NaN. Подробнее см. §3.5.

dconst_<d>

Операция

Помещение double

Формат


dconst_<d>

Формы

dconst_0 = 14 (0xe)

dconst_1 = 15 (0xf)

Стек операндов

... →

..., <d>

Описание

Помещение константы <d> (0.0 или 1.0) на стек операндов.

ddiv

Деление

Деление double

Формат


ddiv

Формы

ddiv = 111 (0x6f)

Стек операндов

..., value1, value2 →

..., result

Описание

Оба value1 и value2 должны быть типа double. Значения извлекаются из стека операндов. Результат result равен value1 / value2. Результат записывается в стек операндов.

Результат инструкции ddiv подчиняется правилам арифметики IEEE 754:

  • Если value1 или value2 равно NaN, результат равен NaN.

  • Если ни value1, ни value2 не равно NaN, знак результата положителен, если оба значения имеют одинаковый знак, и отрицателен, если значения имеют разные знаки.

  • Деление бесконечности на бесконечность приводит к NaN.

  • Деление бесконечности на конечное значение приводит к бесконечности соответствующего знака, с учетом правила определения знака.

  • Деление конечного значения на бесконечность приводит к нулю соответствующего знака, с учетом правила определения знака.

  • Деление нуля на ноль приводит к NaN; деление нуля на любое другое конечное значение приводит к нулю соответствующего знака, с учетом правила определения знака.

  • Деление ненулевого конечного значения на ноль приводит к бесконечности соответствующего знака, с учетом правила определения знака.

  • В остальных случаях, когда ни один операнд не является бесконечностью, нулём или NaN, частное вычисляется и округляется до ближайшего double используя политику округления до ближайшего (§2.8). Если значение слишком велико для представления в качестве double, операция переполняется; результат тогда является бесконечностью соответствующего знака. Если значение слишком мало для представления в качестве double, операция подполняется; результат тогда является нулём соответствующего знака.

Java Virtual Machine требует поддержки постепенного подполнения. Несмотря на то, что могут возникнуть переполнение, подполение, деление на ноль или потеря точности, выполнение инструкции ddiv никогда не вызывает исключения времени выполнения.

dload

Операция

Загрузка double из локальной переменной

Формат


dload
index

Формы

dload = 24 (0x18)

Стек операндов

... →

..., value

Описание

index – это беззнаковый байт. И index, и index+1 должны быть индексами в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу index должна содержать double. Значение локальной переменной по индексу index помещается в стек операндов.

Примечания

Инструкция dload может использоваться совместно с инструкцией wide (§wide) для доступа к локальной переменной с помощью двубайтного беззнакового индекса.

dload_<n>

Операция

Загрузка double из локальной переменной

Формат


dload_<n>

Формы

dload_0 = 38 (0x26)

dload_1 = 39 (0x27)

dload_2 = 40 (0x28)

dload_3 = 41 (0x29)

Стек операндов

... →

..., value

Описание

И <n>, и <n>+1 должны быть индексами в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу <n> должна содержать double. Значение локальной переменной по индексу <n> помещается в стек операндов.

Примечания

Каждая из инструкций dload_<n> эквивалентна dload с индексом <n>, за исключением того, что операнд <n> неявный.

dmul

Операция

Умножение double

Формат


dmul

Формы

dmul = 107 (0x6b)

Стек операндов

..., value1, value2 →

..., результат

Описание

Оба value1 и value2 должны быть типа double. Значения извлекаются из стека операндов. Результат результат вычисляется как value1 * value2. Результат помещается на стек операндов.

Результат инструкции dmul определяется правилами арифметики IEEE 754:

  • Если value1 или value2 равно NaN, результат равен NaN.

  • Если ни value1, ни value2 не равны NaN, знак результата положительный, если оба значения имеют одинаковый знак, и отрицательный, если значения имеют разные знаки.

  • Умножение бесконечности на ноль приводит к NaN.

  • Умножение бесконечности на конечное значение приводит к знаковой бесконечности, с использованием правила, приведенного выше.

  • В остальных случаях, где не участвуют бесконечность или NaN, произведение вычисляется и округляется до ближайшего представимого значения с использованием политики округления до ближайшего (§2.8). Если значение слишком велико для представления как double, операция переполняется; результатом будет бесконечность соответствующего знака. Если значение слишком мало для представления как double, операция переполняется; результатом будет ноль соответствующего знака.

Машина Java Virtual требует поддержки постепенного уменьшения. Несмотря на то, что может произойти переполнение, потеря точности или потеря точности, выполнение инструкции dmul никогда не вызывает исключения времени выполнения.

dneg

Операция

Изменение знака double

Формат


dneg

Формы

dneg = 119 (0x77)

Стек операндов

..., value →

..., результат

Описание

Значение должно быть типа double. Оно извлекается из стека операндов. Результат результат — арифметическое отрицание value. Результат помещается на стек операндов.

Для значений с плавающей запятой отрицание не является тем же, что вычитание из нуля. Если x является +0.0, тогда 0.0-x равно +0.0, но -x равно -0.0. Отрицание просто меняет знак double.

Важные частные случаи:

  • Если операнд равен NaN, результат равен NaN (помните, что NaN не имеет знака).

    Машина Java Virtual не приняла более строгое требование из версии IEEE 754 2019, что отрицание изменяет бит знака для всех входов, включая NaN.

  • Если операнд — бесконечность, результат — бесконечность с противоположным знаком.

  • Если операнд — ноль, результат — ноль с противоположным знаком.

drem

Операция

Остаток double

Формат


drem

Формы

drem = 115 (0x73)

Стек операндов

..., value1, value2 →

..., результат

Описание

Оба value1 и value2 должны быть типа double. Значения извлекаются из стека операндов. Результат результат вычисляется и помещается на стек операндов.

Результат инструкции drem не совпадает с результатом операции остатка, определённой в IEEE 754, из-за выбора политики округления в Java Virtual Machine (§2.8). Операция остатка IEEE 754 вычисляет остаток от округленного деления, а не от усечённого, поэтому её поведение не аналогично поведению обычного целочисленного оператора остатка. Вместо этого Java Virtual Machine определяет drem так, чтобы её поведение было аналогично поведению целочисленных инструкций остатка irem и lrem с предполагаемым делением с политикой округления к нулю; это можно сравнить с функцией библиотеки C fmod.

Результат инструкции drem определяется следующими правилами, которые соответствуют арифметике IEEE 754, за исключением того, как вычисляется предполагаемое деление:

  • Если value1 или value2 равно NaN, результат равен NaN.

  • Если ни value1, ни value2 не равно NaN, знак результата равен знаку делимого.

  • Если делимое — бесконечность или делитель — ноль, или оба, результат равен NaN.

  • Если делимое конечное, а делитель — бесконечность, результат равен делимому.

  • Если делимое — ноль, а делитель — конечное число, результат равен делимому.

  • В остальных случаях, когда ни один операнд не является бесконечностью, нулём или NaN, остаток с плавающей запятой результат от делимого value1 и делителя value2 определяется математическим соотношением результат = value1 - (value2 * q), где q — целое число, которое отрицательно только если value1 / value2 отрицательно, и положительно только если value1 / value2 положительно, и его величина наибольшая, без превышения величины истинного математического частного value1 и value2.

Несмотря на то, что может произойти деление на ноль, вычисление инструкции drem никогда не вызывает исключения времени выполнения. Переполнение, потеря точности или потеря точности не могут произойти.

Примечания

Операция остатка IEEE 754 может быть вычислена функциями библиотеки Math.IEEEremainder или StrictMath.IEEEremainder.

dreturn

Операция

Возвращение double из метода

Формат


dreturn

Формы

dreturn = 175 (0xaf)

Стек операндов

..., value →

[пусто]

Описание

Текущий метод должен иметь возвращаемый тип double. Значение value должно быть типа double. Если текущий метод является методом synchronized, монитор, входящий или повторно входящий при вызове метода, обновляется и, возможно, выходит, как если бы выполнялась инструкция monitorexit (§monitorexit) в текущем потоке. Если исключение не выброшено, value извлекается из стека операндов текущей рамки (§2.6) и помещается в стек операндов рамки вызывающего метода. Любые другие значения в стеке операндов текущего метода отбрасываются.

Затем интерпретатор возвращает управление вызывающему методу, восстанавливая рамку вызывающего метода.

Исключения времени выполнения

Если реализация Java Virtual Machine не соблюдает правила структурированного блокирования, описанные в §2.11.10, то если текущий метод является методом synchronized, а текущий поток не является владельцем монитора, входящего или повторно входящего при вызове метода, dreturn генерирует исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит инструкцию monitorexit, но не инструкцию monitorenter, для объекта, на котором метод синхронизирован.

В противном случае, если реализация Java Virtual Machine соблюдает правила структурированного блокирования, описанные в §2.11.10, и если первое из этих правил нарушается во время вызова текущего метода, то dreturn генерирует исключение IllegalMonitorStateException.

dstore

Операция

Сохранение double в локальную переменную

Формат


dstore
index

Формы

dstore = 57 (0x39)

Стек операндов

..., value →

...

Описание

index — это беззнаковый байт. И index, и index+1 должны быть индексами в массив локальных переменных текущей рамки (§2.6). Значение value на вершине стека операндов должно быть типа double. Оно извлекается из стека операндов. Локальные переменные в позициях index и index+1 устанавливаются в значение value.

Примечания

Инструкцию dstore можно использовать совместно с инструкцией wide (§wide) для доступа к локальной переменной с использованием двубайтового беззнакового индекса.

dstore_<n>

Операция

Сохранение double в локальную переменную

Формат


dstore_<n>

Формы

dstore_0 = 71 (0x47)

dstore_1 = 72 (0x48)

dstore_2 = 73 (0x49)

dstore_3 = 74 (0x4a)

Стек операндов

..., value →

...

Описание

И <n>, и <n>+1 должны быть индексами в массив локальных переменных текущей рамки (§2.6). Значение value на вершине стека операндов должно быть типа double. Оно извлекается из стека операндов. Локальные переменные в позициях <n> и <n>+1 устанавливаются в значение value.

Примечания

Каждая из инструкций dstore_<n> эквивалентна инструкции dstore с index равным <n>, за исключением того, что операнд <n> явный.

dsub

Операция

Вычитание double

Формат


dsub

Формы

dsub = 103 (0x67)

Стек операндов

..., value1, value2 →

..., result

Описание

И value1, и value2 должны быть типа double. Значения извлекаются из стека операндов. Результат result — это value1 - value2. Результат помещается в стек операндов.

Для вычитания double, всегда верно, что a-b даёт тот же результат, что и a+(-b). Однако для инструкции dsub, вычитание из нуля не равно отрицанию, потому что если x равно +0.0, то 0.0-x равно +0.0, но -x равно -0.0.

Java Virtual Machine требует поддержки постепенного подпотока. Несмотря на то, что может произойти переполнение, недополнение или потеря точности, выполнение инструкции dsub никогда не генерирует исключение времени выполнения.

dup

Операция

Дублирует верхнее значение стека операндов

Формат


dup

Формы

dup = 89 (0x59)

Стек операндов

..., value →

..., value, value

Описание

Дублирует верхнее значение в стеке операндов и помещает дублированное значение в стек операндов.

Инструкцию dup нельзя использовать, если value не является значением вычислительного типа категории 1 (§2.11.1).

dup_x1

Операция

Дублирует верхнее значение стека операндов и вставляет два значения вниз

Формат


dup_x1

Формы

dup_x1 = 90 (0x5a)

Стек операндов

..., value2, value1 →

..., value1, value2, value1

Описание

Дублирует верхнее значение в стеке операндов и вставляет дублированное значение на два значения вниз в стеке операндов.

Инструкцию dup_x1 нельзя использовать, если оба value1 и value2 являются значениями вычислительного типа категории 1 (§2.11.1).

dup_x2

Операция

Дублирует верхнее значение стека операндов и вставляет два или три значения вниз

Формат


dup_x2

Формы

dup_x2 = 91 (0x5b)

Стек операндов

Форма 1:

..., value3, value2, value1 →

..., value1, value3, value2, value1

где value1, value2 и value3 - значения вычислительного типа категории 1 (§2.11.1).

Форма 2:

..., value2, value1 →

..., value1, value2, value1

где value1 - значение вычислительного типа категории 1, а value2 - значение вычислительного типа категории 2 (§2.11.1).

Описание

Дублирует верхнее значение в стеке операндов и вставляет дублированное значение на два или три значения вниз в стеке операндов.

dup2

Операция

Дублирует верхнее одно или два значения стека операндов

Формат


dup2

Формы

dup2 = 92 (0x5c)

Стек операндов

Форма 1:

..., value2, value1 →

..., value2, value1, value2, value1

где оба value1 и value2 являются значениями вычислительного типа категории 1 (§2.11.1).

Форма 2:

..., value →

..., value, value

где value - значение вычислительного типа категории 2 (§2.11.1).

Описание

Дублирует верхнее одно или два значения стека операндов и помещает дублированные значения обратно в стек операндов в исходном порядке.

dup2_x1

Операция

Дублирует верхнее одно или два значения стека операндов и вставляет два или три значения вниз

Формат


dup2_x1

Формы

dup2_x1 = 93 (0x5d)

Стек операндов

Форма 1:

..., value3, value2, value1 →

..., value2, value1, value3, value2, value1

где value1, value2 и value3 - значения вычислительного типа категории 1 (§2.11.1).

Форма 2:

..., value2, value1 →

..., value1, value2, value1

где value1 - значение вычислительного типа категории 2, а value2 - значение вычислительного типа категории 1 (§2.11.1).

Описание

Дублирует верхнее одно или два значения стека операндов и вставляет дублированные значения в исходном порядке на одно значение ниже исходного значения или значений в стеке операндов.

dup2_x2

Операция

Дублирует верхнее значение или два верхних значения стека операндов и вставляет их на 2, 3 или 4 позиции вниз

Формат


dup2_x2

Формы

dup2_x2 = 94 (0x5e)

Стек операндов

Форма 1:

..., value4, value3, value2, value1 →

..., value2, value1, value4, value3, value2, value1

где value1, value2, value3 и value4 — значения категорий 1 вычислительного типа (§2.11.1).

Форма 2:

..., value3, value2, value1 →

..., value1, value3, value2, value1

где value1 — значение категории 2 вычислительного типа, а value2 и value3 — значения категории 1 вычислительного типа (§2.11.1).

Форма 3:

..., value3, value2, value1 →

..., value2, value1, value3, value2, value1

где value1 и value2 — значения категории 1 вычислительного типа, а value3 — значение категории 2 вычислительного типа (§2.11.1).

Форма 4:

..., value2, value1 →

..., value1, value2, value1

где value1 и value2 — значения категории 2 вычислительного типа (§2.11.1).

Описание

Дублирует одно или два верхних значения в стеке операндов и вставляет их обратно в стек в исходном порядке.

f2d

Операция

Преобразовать float в double

Формат


f2d

Формы

f2d = 141 (0x8d)

Стек операндов

..., value →

..., result

Описание

Значение value вверху стека операндов должно быть типа float. Оно извлекается из стека операндов и преобразуется в double result. Результат result помещается на стек операндов.

Примечания

Инструкция f2d выполняет расширяющее приведение примитивных типов (JLS §5.1.2).

f2i

Операция

Преобразовать float в int

Формат


f2i

Формы

f2i = 139 (0x8b)

Стек операндов

..., value →

..., result

Описание

Значение value вверху стека операндов должно быть типа float. Оно извлекается из стека операндов и преобразуется в целочисленный тип result. Результат помещается на стек операндов:

  • Если value — NaN, то result — 0.

  • В противном случае, если value не является бесконечностью, оно округляется до целого значения V по правилу округления к нулю (§2.8). Если это целое значение V может быть представлено как int, то result — это значение V.

  • В противном случае, либо value слишком мало (отрицательное значение большой величины или отрицательная бесконечность), и result — наименьшее представимое значение типа int, либо value слишком велико (положительное значение большой величины или положительная бесконечность), и result — наибольшее представимое значение типа int.

Примечания

Инструкция f2i выполняет сужающее приведение примитивных типов (JLS §5.1.3). Она может потерять информацию о величине value и точность.

f2l

Операция

Преобразовать float в long

Формат


f2l

Формы

f2l = 140 (0x8c)

Стек операндов

..., значение →

..., результат

Описание

Значение значение на вершине стека операндов должно быть типа float. Оно извлекается из стека операндов и преобразуется в long результат. Результат помещается на стек операндов:

  • Если значение равно NaN, результатом преобразования является long 0.

  • В противном случае, если значение не является бесконечностью, оно округляется до целого значения V с помощью правила округления к нулю (§2.8). Если это целое значение V может быть представлено как long, то результат — это long значение V.

  • В противном случае, либо значение слишком мало (отрицательное значение большой величины или отрицательная бесконечность), и результат — это наименьшее представимое значение типа long, либо значение слишком велико (положительное значение большой величины или положительная бесконечность), и результат — это наибольшее представимое значение типа long.

Примечания

Инструкция f2l выполняет сужающее примитивное преобразование (JLS §5.1.3). Она может потерять информацию о всей величине значения и также может потерять точность.

fadd

Операция

Сложить float

Формат


fadd

Формы

fadd = 98 (0x62)

Стек операндов

..., значение1, значение2 →

..., результат

Описание

Оба значение1 и значение2 должны быть типа float. Значения извлекаются из стека операндов. float результат — это значение1 + значение2. Результат помещается на стек операндов.

Результат инструкции fadd определяется правилами арифметики IEEE 754:

  • Если значение1 или значение2 равно NaN, результат — NaN.

  • Сумма двух бесконечностей с противоположными знаками — NaN.

  • Сумма двух бесконечностей с одинаковыми знаками — бесконечность с тем же знаком.

  • Сумма бесконечности и любого конечного значения равна бесконечности.

  • Сумма двух нулей с противоположными знаками — положительный ноль.

  • Сумма двух нулей с одинаковыми знаками — ноль с тем же знаком.

  • Сумма нуля и ненулевого конечного значения равна ненулевому значению.

  • Сумма двух ненулевых конечных значений одинаковой величины и противоположных знаков — положительный ноль.

  • В остальных случаях, когда ни один операнд не является бесконечностью, нулём или NaN и значения имеют одинаковый знак или разную величину, сумма вычисляется и округляется до ближайшего представимого значения с помощью правила округления к ближайшему (§2.8). Если величина слишком велика, чтобы быть представленной как float, мы говорим, что операция переполняется; результат — бесконечность соответствующего знака. Если величина слишком мала, чтобы быть представленной как float, мы говорим, что операция подполняется; результат — ноль соответствующего знака.

Машина Java Virtual требует поддержки постепенного подполнения. Несмотря на то, что может произойти переполнение, подпополнение или потеря точности, выполнение инструкции fadd никогда не вызывает исключение времени выполнения.

faload

Операция

Загрузка float из массива

Формат


faload

Формы

faload = 48 (0x30)

Стек операндов

..., ссылка_на_массив, индекс →

..., значение

Описание

ссылка_на_массив должна быть типа reference и должна ссылаться на массив, компоненты которого имеют тип float. Индекс должен быть типа int. Оба ссылка_на_массив и индекс извлекаются из стека операндов. float значение в компоненте массива по индексу извлекается и помещается на стек операндов.

Исключения во время выполнения

Если ссылка_на_массив является null, faload генерирует исключение NullPointerException.

В противном случае, если индекс не находится в пределах границ массива, на который ссылается ссылка_на_массив, инструкция faload генерирует исключение ArrayIndexOutOfBoundsException.

fastore

Операция

Запись в массив float

Формат


fastore

Формы

fastore = 81 (0x51)

Стек операндов

..., arrayref, index, value →

...

Описание

arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип float. index должен быть типа int, а value — типа float. Значения arrayref, index и value извлекаются из стека операндов. Значение value сохраняется в качестве компонента массива с индексом index.

Исключения во время выполнения

Если arrayref является null, fastore генерирует исключение NullPointerException.

В противном случае, если index выходит за пределы границ массива, на который ссылается arrayref, инструкция fastore генерирует исключение ArrayIndexOutOfBoundsException.

fcmp<op>

Операция

Сравнение float

Формат


fcmp<op>

Формы

fcmpg = 150 (0x96)

fcmpl = 149 (0x95)

Стек операндов

..., value1, value2 →

..., result

Описание

И value1, и value2 должны быть типа float. Значения извлекаются из стека операндов, и выполняется сравнение с плавающей запятой:

  • Если value1 больше value2, на стек операндов помещается значение 1.

  • Если value1 равно value2, на стек операндов помещается значение 0.

  • Если value1 меньше value2, на стек операндов помещается значение -1.

  • В противном случае, по крайней мере одно из value1 или value2 — NaN. Инструкция fcmpg помещает на стек операндов значение 1, а fcmpl — значение -1.

Сравнение с плавающей запятой выполняется в соответствии со стандартом IEEE 754. Все значения, кроме NaN, упорядочены, отрицательная бесконечность меньше всех конечных значений, а положительная бесконечность больше всех конечных значений. Положительный и отрицательный ноль считаются равными.

Примечания

Инструкции fcmpg и fcmpl различаются только в обработке сравнения, включающего NaN. NaN не упорядочено, поэтому любое сравнение, если один или оба операнда являются NaN, терпит неудачу. Наличие fcmpg и fcmpl позволяет любое сравнение скомпилировать таким образом, чтобы на стек операндов помещалось одинаковое значение результата, независимо от того, терпит ли сравнение неудачу по значениям, не являющимся NaN, или из-за встреченного NaN. Дополнительная информация в §3.5.

fconst_<f>

Операция

Положить float

Формат


fconst_<f>

Формы

fconst_0 = 11 (0xb)

fconst_1 = 12 (0xc)

fconst_2 = 13 (0xd)

Стек операндов

... →

..., <f>

Описание

Поместить константу float <f> (0.0, 1.0 или 2.0) на стек операндов.

fdiv

Операция

Деление float

Формат


fdiv

Формы

fdiv = 110 (0x6e)

Стек операндов

..., value1, value2 →

..., result

Описание

И value1, и value2 должны быть типа float. Значения извлекаются из стека операндов. float результат result равен value1 / value2. Результат result помещается на стек операндов.

Результат инструкции fdiv определяется правилами арифметики IEEE 754:

  • Если value1 или value2 равны NaN, результат равен NaN.

  • Если ни value1, ни value2 не равны NaN, знак результата положительный, если оба значения имеют одинаковый знак, и отрицательный, если значения имеют разные знаки.

  • Деление бесконечности на бесконечность даёт NaN.

  • Деление бесконечности на конечное значение даёт знаковую бесконечность, со знаком, определяемым только что указанным правилом.

  • Деление конечного значения на бесконечность даёт знаковую единицу, со знаком, определяемым только что указанным правилом.

  • Деление нуля на ноль даёт NaN; деление нуля на любое другое конечное значение даёт знаковую единицу, со знаком, определяемым только что указанным правилом.

  • Деление ненулевого конечного значения на ноль даёт знаковую бесконечность, со знаком, определяемым только что указанным правилом.

  • В оставшихся случаях, когда ни один из операндов не является бесконечностью, нулём или NaN, частное вычисляется и округляется до ближайшего float с использованием правила округления до ближайшего значения (§2.8). Если величина слишком велика для представления в виде float, то говорят об переполнении; результат тогда — бесконечность соответствующего знака. Если величина слишком мала для представления в виде float, то говорят об подпополнении; результат тогда — ноль соответствующего знака.

Java Virtual Machine требует поддержки постепенного подпополнения. Несмотря на то, что может произойти переполнение, подпополнение, деление на ноль или потеря точности, выполнение инструкции fdiv никогда не вызывает исключения во время выполнения.

fload

Операция

Загрузка float из локальной переменной

Формат


fload
index

Формы

fload = 23 (0x17)

Стек операндов

... →

..., value

Описание

index — беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей рамки (§2.6). Локальная переменная в позиции index должна содержать float. Значение value локальной переменной в позиции index помещается на стек операндов.

Примечания

Инструкция fload может использоваться совместно с инструкцией wide (§wide), чтобы получить доступ к локальной переменной с использованием двубайтного беззнакового индекса.

fload_<n>

Операция

Загрузка float из локальной переменной

Формат


fload_<n>

Формы

fload_0 = 34 (0x22)

fload_1 = 35 (0x23)

fload_2 = 36 (0x24)

fload_3 = 37 (0x25)

Стек операндов

... →

..., value

Описание

<n> — индекс в массиве локальных переменных текущей рамки (§2.6). Локальная переменная в позиции <n> должна содержать float. Значение value локальной переменной в позиции <n> помещается на стек операндов.

Примечания

Каждая из инструкций fload_<n> аналогична инструкции fload с индексом <n>, за исключением того, что операнд <n> явный.

fmul

Операция

Умножение float

Формат


fmul

Формы

fmul = 106 (0x6a)

Стек операндов

..., value1, value2 →

..., result

Описание

Оба значения value1 и value2 должны быть типа float. Эти значения извлекаются со стека операндов. Результат result — это value1 * value2. Результат помещается на стек операндов.

Результат инструкции fmul управляется правилами арифметики IEEE 754:

  • Если value1 или value2 равны NaN, результат равен NaN.

  • Если ни value1, ни value2 не равны NaN, знак результата положительный, если оба значения имеют одинаковый знак, и отрицательный, если знаки отличаются.

  • Умножение бесконечности на ноль приводит к NaN.

  • Умножение бесконечности на конечное значение приводит к знаковой бесконечности, учитывая правило определения знака.

  • В оставшихся случаях, когда не участвуют бесконечность или NaN, произведение вычисляется и округляется до ближайшего представимого значения с использованием политики округления до ближайшего (§2.8). Если значение слишком большое, чтобы быть представлено как float, операция считается переполнением; результатом является бесконечность соответствующего знака. Если значение слишком мало, чтобы быть представлено как float, операция считается недополнением; результатом является ноль соответствующего знака.

Виртуальная машина Java требует поддержки постепенного недополнения. Несмотря на то, что может произойти переполнение, недополнение или потеря точности, выполнение инструкции fmul никогда не вызывает исключения времени выполнения.

fneg

Операция

Изменение знака float

Формат


fneg

Формы

fneg = 118 (0x76)

Стек операндов

..., value →

..., result

Описание

Значение value должно быть типа float. Оно извлекается со стека операндов. Результат result — это арифметическое отрицание значения value. Результат помещается на стек операндов.

Для значений float, отрицание не равно вычитанию из нуля. Если x равно +0.0, то 0.0-x равно +0.0, но -x равно -0.0. Унарный минус просто меняет знак float.

Особые случаи:

  • Если операнд равен NaN, результат равен NaN (NaN не имеет знака).

    Виртуальная машина Java не приняла более строгое требование из версии IEEE 754 2019 года, что отрицание инвертирует бит знака для всех входов, включая NaN.

  • Если операнд — бесконечность, результатом является бесконечность противоположного знака.

  • Если операнд — ноль, результатом является ноль противоположного знака.

frem

Операция

Остаток от деления float

Формат


frem

Формы

frem = 114 (0x72)

Стек операндов

..., value1, value2 →

..., result

Описание

Оба значения value1 и value2 должны быть типа float. Значения извлекаются со стека операндов. Результат result вычисляется и помещается на стек операндов.

Результат инструкции frem отличается от результата операции нахождения остатка, определенной в IEEE 754, из-за выбора политики округления в виртуальной машине Java (§2.8). Операция нахождения остатка в IEEE 754 вычисляет остаток от округления деления, а не от усечения, и поэтому ее поведение не аналогично поведению обычного оператора нахождения остатка. Вместо этого виртуальная машина Java определяет frem так, чтобы он вел себя аналогично инструкциям irem и lrem для нахождения остатка целых чисел, с использованием неявного деления с политикой округления к нулю; это можно сравнить с функцией C-библиотеки fmod.

Результат инструкции frem управляется следующими правилами, которые соответствуют арифметике IEEE 754, за исключением того, как вычисляется неявное деление:

  • Если value1 или value2 равны NaN, результатом является NaN.

  • Если ни value1, ни value2 не равны NaN, знак результата равен знаку делимого.

  • Если делимое — бесконечность или делитель — ноль (или оба), результатом является NaN.

  • Если делимое — конечное число, а делитель — бесконечность, результат равен делимому.

  • Если делимое — ноль, а делитель — конечное число, результат равен делимому.

  • В оставшихся случаях, когда ни один из операндов не является бесконечностью, нулем или NaN, остаток с плавающей точкой result от делимого value1 и делителя value2 определяется математическим соотношением result = value1 - (value2 * q), где q — целое число, отрицательное только если value1 / value2 отрицательно, и положительное только если value1 / value2 положительно, и его модуль максимально возможен, не превышая модуля истинного математического частного value1 и value2.

Несмотря на то, что может произойти деление на ноль, вычисление инструкции frem никогда не вызывает исключения времени выполнения. Переполнение, недополнение или потеря точности невозможны.

Примечания

Операцию нахождения остатка IEEE 754 можно вычислить с помощью библиотечной функции Math.IEEEremainder или StrictMath.IEEEremainder.

freturn

Операция

Возврат float из метода

Формат


freturn

Формы

freturn = 174 (0xae)

Стек операндов

..., значение →

[пусто]

Описание

Текущий метод должен иметь тип возвращаемого значения float. Значение значение должно быть типа float. Если текущий метод является методом synchronized, монитор, введённый или повторно введённый при вызове метода, обновляется и, возможно, завершается, как будто выполняется инструкция monitorexit (§monitorexit) в текущей нити. Если исключение не возникает, значение извлекается из стека операндов текущей рамки (§2.6) и помещается в стек операндов рамки вызывающего метода. Все остальные значения в стеке операндов текущего метода удаляются.

Затем интерпретатор возвращает управление вызывающему методу, восстанавливая рамку вызывающего метода.

Исключения во время выполнения

Если реализация Java Virtual Machine не накладывает правил структурированного блокирования, описанных в §2.11.10, то если текущий метод является методом synchronized, а текущая нить не является владельцем монитора, введённого или повторно введённого при вызове метода, freturn вызывает исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит инструкцию monitorexit, но не инструкцию monitorenter для объекта, по которому синхронизируется метод.

В противном случае, если реализация Java Virtual Machine накладывает правила структурированного блокирования, описанные в §2.11.10, и если первое из этих правил нарушается во время вызова текущего метода, то freturn вызывает исключение IllegalMonitorStateException.

fstore

Операция

Сохранение float в локальной переменной

Формат


fstore
индекс

Формы

fstore = 56 (0x38)

Стек операндов

..., значение →

...

Описание

Индекс — это беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей рамки (§2.6). Значение вверху стека операндов должно быть типа float. Оно извлекается из стека операндов, и значение локальной переменной по индексу устанавливается в значение.

Примечания

Инструкция fstore может быть использована совместно с инструкцией wide (§wide) для доступа к локальной переменной с использованием двубайтового беззнакового индекса.

fstore_<n>

Операция

Сохранение float в локальной переменной

Формат


fstore_<n>

Формы

fstore_0 = 67 (0x43)

fstore_1 = 68 (0x44)

fstore_2 = 69 (0x45)

fstore_3 = 70 (0x46)

Стек операндов

..., значение →

...

Описание

<n> должен быть индексом в массиве локальных переменных текущей рамки (§2.6). Значение вверху стека операндов должно быть типа float. Оно извлекается из стека операндов, и значение локальной переменной по <n> устанавливается в значение.

Примечания

Каждая из инструкций fstore_<n> эквивалентна инструкции fstore с индексом <n>, за исключением того, что операнд <n> неявный.

fsub

Операция

Вычитание float

Формат


fsub

Формы

fsub = 102 (0x66)

Стек операндов

..., значение1, значение2 →

..., результат

Описание

И значение1, и значение2 должны быть типа float. Значения извлекаются из стека операндов. Результат результат равен значение1 - значение2. Результат помещается в стек операндов.

При вычитании float всегда верно, что a-b даёт тот же результат, что и a+(-b). Однако для инструкции fsub вычитание из нуля не равно отрицанию, потому что, если x равно +0.0, то 0.0-x равно +0.0, но -x равно -0.0.

Java Virtual Machine требует поддержки постепенного переполнения. Несмотря на то, что может произойти переполнение, недополнение или потеря точности, выполнение инструкции fsub никогда не вызывает исключение во время выполнения.

getfield

Операция

Извлечение поля из объекта

Формат


getfield
indexbyte1
indexbyte2

Формы

getfield = 180 (0xb4)

Стек операндов

..., objectref →

..., value

Описание

Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на поле (§5.1), которая содержит имя и дескриптор поля, а также символическую ссылку на класс, в котором находится поле. Ссылка на поле разрешается (§5.4.3.2).

objectref, который должен быть типа reference, но не типа массива, извлекается из стека операндов. Значение value указанного поля в objectref извлекается и помещается в стек операндов.

Исключения связывания

Во время разрешения символической ссылки на поле могут быть выброшены любые ошибки, относящиеся к разрешению поля (§5.4.3.2).

В противном случае, если разрешенное поле является static полем, getfield выбрасывает исключение IncompatibleClassChangeError.

Исключение времени выполнения

В противном случае, если objectref является null, инструкция getfield выбрасывает исключение NullPointerException.

Примечания

Инструкция getfield не может использоваться для доступа к length полю массива. Вместо этого используется инструкция arraylength (§arraylength).

getstatic

Операция

Получение static поля из класса

Формат


getstatic
indexbyte1
indexbyte2

Формы

getstatic = 178 (0xb2)

Стек операндов

..., →

..., value

Описание

Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на поле (§5.1), которая содержит имя и дескриптор поля, а также символическую ссылку на класс или интерфейс, в котором находится поле. Ссылка на поле разрешается (§5.4.3.2).

При успешном разрешении поля, класс или интерфейс, который объявил разрешенное поле, инициализируется, если этот класс или интерфейс еще не были инициализированы (§5.5).

Значение поля класса или интерфейса извлекается и помещается в стек операндов.

Исключения связывания

Во время разрешения символической ссылки на поле класса или интерфейса могут быть выброшены любые исключения, связанные с разрешением поля (§5.4.3.2).

В противном случае, если разрешенное поле не является static (классовым) полем или полем интерфейса, getstatic выбрасывает исключение IncompatibleClassChangeError.

Исключение времени выполнения

В противном случае, если выполнение этой инструкции getstatic вызывает инициализацию указанного класса или интерфейса, getstatic может выбросить исключение Error, как подробно описано в §5.5.

goto

Операция

Безусловный переход

Формат


goto
branchbyte1
branchbyte2

Формы

goto = 167 (0xa7)

Стек операндов

Без изменений

Описание

Беззнаковые байты branchbyte1 и branchbyte2 используются для построения знакового 16-битного смещения branchoffset, где branchoffset равно (branchbyte1 << 8) | branchbyte2. Выполнение продолжается по смещению от адреса кода операции данной инструкции goto. Целевой адрес должен быть адресом кода операции инструкции внутри метода, содержащего данную инструкцию goto.

goto_w

Операция

Безусловный переход (широкий индекс)

Формат


goto_w
branchbyte1
branchbyte2
branchbyte3
branchbyte4

Формы

goto_w = 200 (0xc8)

Операционная стека

Без изменений

Описание

Беззнаковые байты branchbyte1, branchbyte2, branchbyte3 и branchbyte4 используются для построения знакового 32-битного branchoffset, где branchoffset — это (branchbyte1 << 24) | (branchbyte2 << 16) | (branchbyte3 << 8) | branchbyte4. Выполнение продолжается в этом смещении от адреса операционного кода этой инструкции goto_w. Целевой адрес должен соответствовать операционному коду инструкции в методе, содержащем эту инструкцию goto_w.

Примечания

Несмотря на то, что инструкция goto_w использует 4-байтовое смещение ветвления, другие факторы ограничивают размер метода до 65535 байтов (§4.11). Это ограничение может быть увеличено в будущих версиях Java Virtual Machine.

i2b

Операция

Преобразование int в byte

Формат


i2b

Формы

i2b = 145 (0x91)

Операционная стека

..., value →

..., result

Описание

Значение value на вершине операционной стеки должно быть типа int. Оно извлекается из операционной стеки, усекается до byte, затем расширяется со знаком до int result. Значение result помещается на операционную стеку.

Примечания

Инструкция i2b выполняет сужение примитивного преобразования (JLS §5.1.3). Она может потерять информацию о величине value. Результат result также может иметь другой знак, чем value.

i2c

Операция

Преобразование int в char

Формат


i2c

Формы

i2c = 146 (0x92)

Операционная стека

..., value →

..., result

Описание

Значение value на вершине операционной стеки должно быть типа int. Оно извлекается из операционной стеки, усекается до char, затем расширяется без знака до int result. Значение result помещается на операционную стеку.

Примечания

Инструкция i2c выполняет сужение примитивного преобразования (JLS §5.1.3). Она может потерять информацию о величине value. Результат result (который всегда положителен) также может иметь другой знак, чем value.

i2d

Операция

Преобразование int в double

Формат


i2d

Формы

i2d = 135 (0x87)

Операционная стека

..., value →

..., result

Описание

Значение value на вершине операционной стеки должно быть типа int. Оно извлекается из операционной стеки и преобразуется в double result. Значение result помещается на операционную стеку.

Примечания

Инструкция i2d выполняет расширение примитивного преобразования (JLS §5.1.2). Поскольку все значения типа int точно представимы типом double, преобразование точное.

i2f

Операция

Преобразование int в float

Формат


i2f

Формы

i2f = 134 (0x86)

Операционная стека

..., value →

..., result

Описание

Значение value на вершине операционной стеки должно быть типа int. Оно извлекается из операционной стеки и преобразуется в float result с использованием политики округления до ближайшего значения (§2.8). Значение result помещается на операционную стеку.

Примечания

Инструкция i2f выполняет расширение примитивного преобразования (JLS §5.1.2), но может привести к потере точности, поскольку значения типа float имеют только 24 значащих бита.

i2l

Операция

Преобразовать int в long

Формат


i2l

Формы

i2l = 133 (0x85)

Стек операндов

..., значение →

..., результат

Описание

Значение значение на вершине стека операндов должно быть типа int. Оно извлекается из стека операндов и расширяется со знаком до long результат. Результат помещается в стек операндов.

Примечания

Инструкция i2l выполняет расширяющее примитивное преобразование (JLS §5.1.2). Поскольку все значения типа int точно представимы типом long, преобразование точное.

i2s

Операция

Преобразовать int в short

Формат


i2s

Формы

i2s = 147 (0x93)

Стек операндов

..., значение →

..., результат

Описание

Значение значение на вершине стека операндов должно быть типа int. Оно извлекается из стека операндов, обрезается до short, затем расширяется со знаком до int результат. Результат помещается в стек операндов.

Примечания

Инструкция i2s выполняет сужающее примитивное преобразование (JLS §5.1.3). Она может потерять информацию о величине значение. Результат также может не иметь того же знака, что и значение.

iadd

Операция

Сложить int

Формат


iadd

Формы

iadd = 96 (0x60)

Стек операндов

..., значение1, значение2 →

..., результат

Описание

Значение1 и Значение2 должны быть типа int. Значения извлекаются из стека операндов. Результат – это значение1 + значение2. Результат помещается в стек операндов.

Результат — 32 младших бита истинного математического результата в формате со знаком дополнения до двух достаточной ширины, представленный как значение типа int. Если происходит переполнение, то знак результата может не совпадать со знаком математической суммы двух значений.

Несмотря на то, что переполнение может произойти, выполнение инструкции iadd никогда не генерирует исключение во время выполнения.

iaload

Операция

Загрузка int из массива

Формат


iaload

Формы

iaload = 46 (0x2e)

Стек операндов

..., ссылка_на_массив, индекс →

..., значение

Описание

Ссылка_на_массив должна быть типа reference и должна ссылаться на массив, компоненты которого являются типа int. Индекс должен быть типа int. Обе ссылка_на_массив и индекс извлекаются из стека операндов. Значение в компоненте массива по индексу извлекается и помещается в стек операндов.

Исключения во время выполнения

Если ссылка_на_массив является null, iaload генерирует исключение NullPointerException.

В противном случае, если индекс выходит за пределы массива, на который ссылается ссылка_на_массив, инструкция iaload генерирует исключение ArrayIndexOutOfBoundsException.

iand

Операция

Логическое И int

Формат


iand

Формы

iand = 126 (0x7e)

Стек операндов

..., значение1, значение2 →

..., результат

Описание

Значение1 и Значение2 должны быть типа int. Они извлекаются из стека операндов. Результат – это побитовое И (конъюнкция) значение1 и значение2. Результат помещается в стек операндов.

iastore

Операция

Запись в массив int

Формат


iastore

Формы

iastore = 79 (0x4f)

Стек операндов

..., arrayref, index, value →

...

Описание

arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип int. И index, и value должны быть типа int. arrayref, index и value извлекаются со стека операндов. Значение value сохраняется в качестве компонента массива с индексом index.

Исключения во время выполнения

Если arrayref является null, iastore генерирует исключение NullPointerException.

В противном случае, если index не находится в пределах границ массива, на который ссылается arrayref, инструкция iastore генерирует исключение ArrayIndexOutOfBoundsException.

iconst_<i>

Операция

Положить константу int

Формат


iconst_<i>

Формы

iconst_m1 = 2 (0x2)

iconst_0 = 3 (0x3)

iconst_1 = 4 (0x4)

iconst_2 = 5 (0x5)

iconst_3 = 6 (0x6)

iconst_4 = 7 (0x7)

iconst_5 = 8 (0x8)

Стек операндов

... →

..., <i>

Описание

Поместить константу int <i> (-1, 0, 1, 2, 3, 4 или 5) на стек операндов.

Примечания

Каждая из инструкций этого семейства эквивалентна bipush <i> для соответствующего значения <i>, за исключением того, что операнд <i> неявный.

idiv

Операция

Деление int

Формат


idiv

Формы

idiv = 108 (0x6c)

Стек операндов

..., value1, value2 →

..., result

Описание

И value1, и value2 должны быть типа int. Значения извлекаются со стека операндов. Полученный result - значение выражения языка программирования Java value1 / value2 (JLS §15.17.2). result помещается на стек операндов.

Деление округляется к нулю; другими словами, частное, полученное для int значений в n/d, является значением q, модуль которого максимально возможен при удовлетворении |d ⋅ q| ≤ |n|. Кроме того, q положительно, когда |n| ≥ |d| и n и d имеют одинаковый знак, но q отрицательно, когда |n| ≥ |d| и n и d имеют противоположные знаки.

Существует один особый случай, который не удовлетворяет этому правилу: если делимое является целым числом с наибольшим возможным модулем для типа int, а делитель равен -1, то происходит переполнение, и результат равен делимому. Несмотря на переполнение, исключение в этом случае не генерируется.

Исключение во время выполнения

Если значение делителя в int делении равно 0, idiv генерирует исключение ArithmeticException.

if_acmp<cond>

Операция

Разветвление, если reference сравнение успешно

Формат


if_acmp<cond>
branchbyte1
branchbyte2

Формы

if_acmpeq = 165 (0xa5)

if_acmpne = 166 (0xa6)

Стек операндов

..., value1, value2 →

...

Описание

Оба value1 и value2 должны быть типа reference. Они оба извлекаются из стека операндов и сравниваются. Результаты сравнения следующие:

  • if_acmpeq успешно, если и только если value1 = value2

  • if_acmpne успешно, если и только если value1 ≠ value2

Если сравнение успешно, незначащие branchbyte1 и branchbyte2 используются для построения знакового 16-битного смещения, где смещение вычисляется как (branchbyte1 << 8) | branchbyte2. Выполнение затем продолжается по этому смещению от адреса кода этой инструкции if_acmp<cond>. Целевой адрес должен быть адресом кода инструкции внутри метода, содержащего эту инструкцию if_acmp<cond>.

В противном случае, если сравнение не выполнено, выполнение продолжается по адресу инструкции, следующей за этой инструкцией if_acmp<cond>.

if_icmp<cond>

Операция

Разветвление, если int сравнение успешно

Формат


if_icmp<cond>
branchbyte1
branchbyte2

Формы

if_icmpeq = 159 (0x9f)

if_icmpne = 160 (0xa0)

if_icmplt = 161 (0xa1)

if_icmpge = 162 (0xa2)

if_icmpgt = 163 (0xa3)

if_icmple = 164 (0xa4)

Стек операндов

..., value1, value2 →

...

Описание

Оба value1 и value2 должны быть типа int. Они оба извлекаются из стека операндов и сравниваются. Все сравнения являются знаковыми. Результаты сравнения следующие:

  • if_icmpeq успешно, если и только если value1 = value2

  • if_icmpne успешно, если и только если value1 ≠ value2

  • if_icmplt успешно, если и только если value1 < value2

  • if_icmple успешно, если и только если value1 ≤ value2

  • if_icmpgt успешно, если и только если value1 > value2

  • if_icmpge успешно, если и только если value1 ≥ value2

Если сравнение успешно, незначащие branchbyte1 и branchbyte2 используются для построения знакового 16-битного смещения, где смещение вычисляется как (branchbyte1 << 8) | branchbyte2. Выполнение затем продолжается по этому смещению от адреса кода этой инструкции if_icmp<cond>. Целевой адрес должен быть адресом кода инструкции внутри метода, содержащего эту инструкцию if_icmp<cond>.

В противном случае, выполнение продолжается по адресу инструкции, следующей за этой инструкцией if_icmp<cond>.

if<cond>

Операция

Ветвление, если int сравнение со значением ноль имеет успех

Формат


if<cond>
branchbyte1
branchbyte2

Формы

ifeq = 153 (0x99)

ifne = 154 (0x9a)

iflt = 155 (0x9b)

ifge = 156 (0x9c)

ifgt = 157 (0x9d)

ifle = 158 (0x9e)

Стек операндов

..., value →

...

Описание

Значение value должно быть типа int. Оно извлекается из стека операндов и сравнивается с нулём. Все сравнения являются знаковыми. Результаты сравнений следующие:

  • ifeq выполняется тогда и только тогда, когда value = 0

  • ifne выполняется тогда и только тогда, когда value ≠ 0

  • iflt выполняется тогда и только тогда, когда value < 0

  • ifle выполняется тогда и только тогда, когда value ≤ 0

  • ifgt выполняется тогда и только тогда, когда value > 0

  • ifge выполняется тогда и только тогда, когда value ≥ 0

Если сравнение успешно, то беззнаковые branchbyte1 и branchbyte2 используются для построения знакового 16-разрядного смещения, где смещение вычисляется как (branchbyte1 << 8) | branchbyte2. Выполнение затем продолжается по этому смещению от адреса кода этой инструкции if<cond>. Целевой адрес должен быть адресом кода инструкции внутри метода, который содержит эту инструкцию if<cond>.

В противном случае выполнение продолжается по адресу инструкции, следующей за этой инструкцией if<cond>.

ifnonnull

Операция

Ветвление, если reference не null

Формат


ifnonnull
branchbyte1
branchbyte2

Формы

ifnonnull = 199 (0xc7)

Стек операндов

..., value →

...

Описание

value должно быть типа reference. Оно извлекается из стека операндов. Если value не null, то беззнаковые branchbyte1 и branchbyte2 используются для построения знакового 16-разрядного смещения, где смещение вычисляется как (branchbyte1 << 8) | branchbyte2. Выполнение затем продолжается по этому смещению от адреса кода этой инструкции ifnonnull. Целевой адрес должен быть адресом кода инструкции внутри метода, который содержит эту инструкцию ifnonnull.

В противном случае выполнение продолжается по адресу инструкции, следующей за этой инструкцией ifnonnull.

ifnull

Операция

Ветвление, если reference является null

Формат


ifnull
branchbyte1
branchbyte2

Формы

ifnull = 198 (0xc6)

Стек операндов

..., value →

...

Описание

value должно быть типа reference. Оно извлекается из стека операндов. Если value является null, то беззнаковые branchbyte1 и branchbyte2 используются для построения знакового 16-разрядного смещения, где смещение вычисляется как (branchbyte1 << 8) | branchbyte2. Выполнение затем продолжается по этому смещению от адреса кода этой инструкции ifnull. Целевой адрес должен быть адресом кода инструкции внутри метода, который содержит эту инструкцию ifnull.

В противном случае выполнение продолжается по адресу инструкции, следующей за этой инструкцией ifnull.

iinc

Операция

Увеличение локальной переменной на константу

Формат


iinc
index
const

Формы

iinc = 132 (0x84)

Стек операндов

Без изменений

Описание

index — беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей рамки (§2.6). const — непосредственный знаковый байт. Локальная переменная по индексу index должна содержать int. Значение const сначала расширяется со знаком до int, а затем локальная переменная по индексу index увеличивается на эту величину.

Примечания

Команда iinc может использоваться вместе с инструкцией wide (§wide) для доступа к локальной переменной с помощью двубайтового беззнакового индекса и увеличения её на двубайтовое знаковое значение.

iload

Операция

Загрузка int из локальной переменной

Формат


iload
индекс

Формы

iload = 21 (0x15)

Стек операндов

... →

..., значение

Описание

Индекс — это беззнаковый байт, который должен быть индексом в массив локальных переменных текущей рамки (§2.6). Локальная переменная по индексу должна содержать int. Значение локальной переменной по индексу помещается в стек операндов.

Примечания

Инструкцию iload можно использовать совместно с инструкцией wide (§wide) для доступа к локальной переменной с использованием двухбайтового беззнакового индекса.

iload_<n>

Операция

Загрузка int из локальной переменной

Формат


iload_<n>

Формы

iload_0 = 26 (0x1a)

iload_1 = 27 (0x1b)

iload_2 = 28 (0x1c)

iload_3 = 29 (0x1d)

Стек операндов

... →

..., значение

Описание

<n> — это индекс в массив локальных переменных текущей рамки (§2.6). Локальная переменная по <n> должна содержать int. Значение локальной переменной по <n> помещается в стек операндов.

Примечания

Каждая из инструкций iload_<n> идентична инструкции iload с индексом <n>, за исключением того, что операнд <n> неявный.

imul

Операция

Умножение int

Формат


imul

Формы

imul = 104 (0x68)

Стек операндов

..., значение1, значение2 →

..., результат

Описание

значение1 и значение2 должны быть типа int. Эти значения извлекаются из стека операндов. Результат результат — это значение1 * значение2. Результат помещается в стек операндов.

Результат — это 32 младших бита истинного математического результата в достаточно широком формате дополнения до двух, представленном как значение типа int. Если происходит переполнение, то знак результата может не совпадать со знаком математического умножения двух значений.

Несмотря на то, что переполнение может произойти, выполнение инструкции imul никогда не вызывает исключения во время выполнения.

ineg

Операция

Отрицание int

Формат


ineg

Формы

ineg = 116 (0x74)

Стек операндов

..., значение →

..., результат

Описание

Значение должно быть типа int. Оно извлекается из стека операндов. Результат результат — это арифметическое отрицание значения, -значение. Результат помещается в стек операндов.

Для значений int, отрицание равно вычитанию из нуля. Поскольку Java Virtual Machine использует представление целых чисел в дополнении до двух, и диапазон значений в дополнении до двух не симметричен, отрицание максимального отрицательного int приводит к тому же максимальному отрицательному числу. Несмотря на то, что произошло переполнение, исключение не генерируется.

Для всех значений int x, -x равно (~x)+1.

instanceof

Операция

Определить, является ли объект заданного типа

Формат


instanceof
indexbyte1
indexbyte2

Формы

instanceof = 193 (0xc1)

Стек операндов

..., objectref →

..., result

Описание

Объект objectref, который должен быть типа reference, извлекается из стека операндов. Беззнаковые значения indexbyte1 и indexbyte2 используются для построения индекса в пуле постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения по этому индексу должен быть символической ссылкой на класс, массив или тип интерфейса.

Если objectref равен null, инструкция instanceof помещает в стек операндов значение результата 0 как int.

В противном случае, заданный класс, массив или тип интерфейса разрешаются (§5.4.3.1). Если objectref является экземпляром разрешенного класса или типа массива, или реализует разрешенный интерфейс, инструкция instanceof помещает в стек операндов значение результата 1 как int; в противном случае, она помещает значение результата 0.

Для определения, является ли objectref, который не равен null, экземпляром разрешенного типа, используются следующие правила. Если S — тип объекта, на который ссылается objectref, а T — разрешенный класс, массив или тип интерфейса, тогда instanceof определяет, является ли objectref экземпляром T следующим образом:

  • Если S — тип класса, то:

    • Если T — тип класса, то S должен быть таким же классом, как T, или S должен быть подклассом T;

    • Если T — тип интерфейса, то S должен реализовывать интерфейс T.

  • Если S — тип массива SC[], то есть массив компонентов типа SC, то:

    • Если T — тип класса, то T должен быть Object.

    • Если T — тип интерфейса, то T должен быть одним из интерфейсов, реализуемых массивами (JLS §4.10.3).

    • Если T — тип массива TC[], то есть массив компонентов типа TC, то одно из следующих условий должно выполняться:

      • TC и SC — тот же примитивный тип.

      • TC и SC — ссылочные типы, и тип SC может быть преобразован к типу TC по этим правилам времени выполнения.

Исключения при установлении связи

Во время разрешения символической ссылки на класс, массив или тип интерфейса могут быть выброшены любые исключения, описанные в §5.4.3.1.

Примечания

Инструкция instanceof очень похожа на инструкцию checkcast (§checkcast). Она отличается обработкой null, своим поведением при неудачном тесте (checkcast генерирует исключение, instanceof помещает код результата) и своим влиянием на стек операндов.

invokedynamic

Операция

Вызов динамически вычисляемого места вызова

Формат


invokedynamic
indexbyte1
indexbyte2
0
0

Формы

invokedynamic = 186 (0xba)

Стек операндов

..., [arg1, [arg2 ...]] →

...

Описание

Сначала неотрицательные значения indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на динамически вычисляемое место вызова (§5.1). Значения третьего и четвёртого байтов операндов всегда должны быть равны нулю.

Символическая ссылка разрешается (§5.4.3.6) для данной конкретной инструкции invokedynamic, чтобы получить reference к экземпляру java.lang.invoke.CallSite. Экземпляр java.lang.invoke.CallSite считается «связанным» с данной конкретной инструкцией invokedynamic.

Экземпляр java.lang.invoke.CallSite указывает на обработчик метода-цели. Значения аргументов nargs извлекаются из стека операндов, и обработчик метода-цели вызывается. Вызов происходит так, как если бы выполнялась инструкция invokevirtual, которая указывает индекс постоянного пула времени выполнения на символическую ссылку R, где:

  • R — это символическая ссылка на метод класса;

  • для символической ссылки на класс, в котором должен находиться метод, R указывает java.lang.invoke.MethodHandle;

  • для имени метода R указывает invokeExact;

  • для описания метода R указывает описание метода в динамически вычисляемом месте вызова.

и как будто следующие элементы в порядке поочередности помещаются в стек операндов:

  • ссылка reference на обработчик метода-цели;

  • значения аргументов nargs, где количество, тип и порядок значений должны соответствовать описанию метода в динамически вычисляемом месте вызова.

Исключения привязке

Во время разрешения символической ссылки на динамически вычисляемое место вызова могут быть выброшены любые исключения, связанные с разрешением динамически вычисляемого места вызова.

Примечания

Если символическая ссылка на динамически вычисляемое место вызова может быть разрешена, это подразумевает, что не-null reference к экземпляру java.lang.invoke.CallSite привязано к инструкции invokedynamic. Поэтому обработчик метода-цели, указанный экземпляром java.lang.invoke.CallSite, не является null.

Аналогично, успешное разрешение подразумевает, что описание метода в символической ссылке семантически равно типу описания обработчика метода-цели.

Вместе эти инварианты означают, что инструкция invokedynamic, которая привязана к экземпляру java.lang.invoke.CallSite, никогда не вызывает исключение NullPointerException или java.lang.invoke.WrongMethodTypeException.

invokeinterface

Операция

Вызов метода интерфейса

Формат


invokeinterface
indexbyte1
indexbyte2
count
0

Формы

invokeinterface = 185 (0xb9)

Стек операндов

..., objectref, [arg1, [arg2 ...]] →

...

Описание

Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения по этому индексу должен быть символической ссылкой на метод интерфейса (§5.1), который задаёт имя и дескриптор (§4.3.3) метода интерфейса, а также символическую ссылку на интерфейс, в котором находится метод интерфейса. Названный метод интерфейса разрешается (§5.4.3.4).

Разрешённый метод интерфейса не должен быть методом инициализации экземпляра или методом инициализации класса или интерфейса (§2.9.1, §2.9.2).

Операнд count — это беззнаковый байт, который не должен быть равен нулю. objectref должен быть типа reference и должен следовать за ним в стеке операндов nargs значениями аргументов, где количество, тип и порядок значений должны соответствовать дескриптору разрешённого метода интерфейса. Значение четвёртого байта операнда должно всегда быть нулём.

Пусть C — класс objectref. Метод выбирается относительно C и разрешённого метода (§5.4.6). Это вызываемый метод.

Если вызываемый метод является synchronized, монитор, связанный с objectref, входит или повторно входит, как если бы выполнялась инструкция monitorenter (§monitorenter) в текущем потоке.

Если вызываемый метод не является native, nargs значения аргументов и objectref извлекаются из стека операндов. Для вызываемого метода создаётся новая рамка в стеке виртуальной машины Java. objectref и значения аргументов последовательно становятся значениями локальных переменных новой рамки, причём objectref в локальной переменной 0, arg1 в локальной переменной 1 (или, если arg1 имеет тип long или double, в локальных переменных 1 и 2), и так далее. Затем новая рамка становится текущей, и виртуальная машина Java устанавливает текущий opcode на код первой инструкции вызываемого метода. Выполнение продолжается с первой инструкции метода.

Если вызываемый метод является native и зависящий от платформы код, который его реализует, ещё не привязан (§5.6) к виртуальной машине Java, то это делается. Значения аргументов nargs и objectref извлекаются из стека операндов и передаются в качестве параметров коду, который реализует метод. Параметры передаются, и код вызывается способом, зависящим от реализации. Когда код зависящий от платформы возвращается:

  • Если метод native является synchronized, монитор, связанный с objectref, обновляется и, возможно, покидает, как если бы выполнялась инструкция monitorexit (§monitorexit) в текущем потоке.

  • Если метод native возвращает значение, возвращаемое значение кода, зависящего от платформы, преобразуется способом, зависящим от реализации, к типу возвращаемого значения метода native и помещается в стек операндов.

Исключения привязке

Во время разрешения символической ссылки на метод интерфейса могут быть выброшены любые исключения, относящиеся к разрешению метода интерфейса (§5.4.3.4).

В противном случае, если разрешённый метод является static, инструкция invokeinterface выбрасывает IncompatibleClassChangeError.

Обратите внимание, что invokeinterface может ссылаться на private методы, объявленные в интерфейсах, включая интерфейсы nestmate.

Исключения времени выполнения

В противном случае, если objectref является null, инструкция invokeinterface выбрасывает NullPointerException.

В противном случае, если класс objectref не реализует разрешённый интерфейс, invokeinterface выбрасывает IncompatibleClassChangeError.

В противном случае, если выбранный метод не является ни public, ни private, invokeinterface выбрасывает IllegalAccessError.

В противном случае, если выбранный метод является abstract, invokeinterface выбрасывает AbstractMethodError.

В противном случае, если выбранный метод является native, и код, реализующий метод, не может быть привязан, invokeinterface выбрасывает UnsatisfiedLinkError.

В противном случае, если метод не выбран, и существует несколько максимально-специфичных методов суперинтерфейса C, которые соответствуют имени и дескриптору разрешённого метода и не являются abstract, invokeinterface выбрасывает IncompatibleClassChangeError

В противном случае, если метод не выбран, и нет максимально-специфичных методов суперинтерфейса C, которые соответствуют имени и дескриптору разрешённого метода и не являются abstract, invokeinterface выбрасывает AbstractMethodError.

Примечания

Операнд count инструкции invokeinterface записывает меру количества значений аргументов, где значение аргумента типа long или типа double вносит два единицы в значение count, а аргумент любого другого типа вносит одну единицу. Эта информация также может быть получена из дескриптора выбранного метода. Избыточность носит исторический характер.

Четвёртый байт операнда существует для резервирования места для дополнительного операнда, используемого в некоторых реализациях виртуальной машины Java Oracle, которые заменяют инструкцию invokeinterface специализированной псевдоинструкцией во время выполнения. Он должен быть сохранён для обеспечения обратной совместимости.

Значения аргументов nargs и objectref не являются взаимно однозначными с первыми nargs+1 локальными переменными. Значения аргументов типов long и double должны храниться в двух последовательных локальных переменных, поэтому может потребоваться больше, чем nargs локальных переменных для передачи nargs значений аргументов вызываемому методу.

Логика выбора позволяет выбрать метод, не являющийся abstract, объявленный в суперинтерфейсе. Методы в интерфейсах рассматриваются только в том случае, если нет соответствующего метода в иерархии классов. В случае, если в иерархии суперинтерфейсов существуют два метода, не являющиеся abstract, и ни один из них не является более специфичным, возникает ошибка; попытка уточнения не предпринимается (например, один может быть искомым методом, а другой — не связанным, но мы не отдаём предпочтение искомому методу). С другой стороны, если существует много методов abstract, но только один метод, не являющийся abstract, выбирается метод, не являющийся abstract (если метод, не являющийся abstract, не является более специфичным).

invokespecial

Операция

Вызов метода экземпляра; прямой вызов методов инициализации экземпляра и методов текущего класса и его супертипов

Формат


invokespecial
indexbyte1
indexbyte2

Формы

invokespecial = 183 (0xb7)

Стек операндов

..., objectref, [arg1, [arg2 ...]] →

...

Описание

Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пул постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Запись в пуле постоянных времени выполнения по указанному индексу должна быть символической ссылкой на метод или метод интерфейса (§5.1), которая задаёт имя и дескриптор (§4.3.3) метода или метода интерфейса, а также символическую ссылку на класс или интерфейс, в котором находится метод или метод интерфейса. Имя метода разрешается (§5.4.3.3, §5.4.3.4).

Если выполняются все следующие условия, пусть C — непосредственный суперкласс текущего класса:

  • Разрешённый метод не является методом инициализации экземпляра (§2.9.1).

  • Символическая ссылка указывает на класс (не интерфейс), и этот класс является суперклассом текущего класса.

  • Флаг ACC_SUPER установлен для файла class (§4.1).

В противном случае пусть C — класс или интерфейс, указанный в символической ссылке.

Фактический вызываемый метод выбирается по следующему алгоритму поиска:

  1. Если C содержит объявление метода экземпляра с тем же именем и дескриптором, что и разрешённый метод, то это вызываемый метод.

  2. В противном случае, если C — класс и имеет суперкласс, выполняется поиск объявления метода экземпляра с тем же именем и дескриптором, начиная с непосредственного суперкласса C и продолжая с непосредственного суперкласса этого класса и так далее, пока не будет найдена совпадающая запись или не останется больше суперклассов. Если совпадение найдено, то это вызываемый метод.

  3. В противном случае, если C — интерфейс и класс Object содержит объявление метода экземпляра public с тем же именем и дескриптором, что и разрешённый метод, то это вызываемый метод.

  4. В противном случае, если ровно один максимально специфичный метод (§5.4.3.3) в суперинтерфейсах C соответствует имени и дескриптору разрешённого метода и не является abstract, то это вызываемый метод.

objectref должен быть типа reference и должен следовать за ним в стеке операндов nargs значениями аргументов, где количество, тип и порядок значений должны быть согласованы с дескриптором выбранного метода экземпляра.

Если метод является synchronized, монитор, связанный с objectref, вводится или повторно вводится как при выполнении инструкции monitorenter (§monitorenter) в текущем потоке.

Если метод не является native, nargs значения аргументов и objectref извлекаются из стека операндов. В стеке виртуальной машины Java создается новый фрейм для вызываемого метода. objectref и значения аргументов поочередно становятся значениями локальных переменных нового фрейма, при этом objectref в локальной переменной 0, arg1 в локальной переменной 1 (или, если arg1 типа long или double, в локальных переменных 1 и 2), и так далее. Затем новый фрейм становится текущим, и виртуальная машина Java устанавливает код первого оператора вызываемого метода. Выполнение продолжается с первого оператора метода.

Если метод является native и зависимый от платформы код, его реализующий, ещё не привязан (§5.6) к виртуальной машине Java, это делается. Значения nargs аргументов и objectref извлекаются из стека операндов и передаются в качестве параметров коду, реализующему метод. Параметры передаются, и код вызывается зависимым от реализации способом. Когда зависимый от платформы код возвращается, выполняются следующие действия:

  • Если метод native является synchronized, монитор, связанный с objectref, обновляется и, возможно, выходит, как при выполнении инструкции monitorexit (§monitorexit) в текущем потоке.

  • Если метод native возвращает значение, возвращаемое значение зависимого от платформы кода преобразуется зависимым от реализации способом в возвращаемый тип метода native и помещается в стек операндов.

Исключения при связывании

При разрешении символической ссылки на метод могут быть сгенерированы любые исключения, связанные с разрешением метода (§5.4.3.3).

В противном случае, если разрешённый метод является методом инициализации экземпляра, и класс, в котором он объявлен, не является классом, символически указанным в инструкции, генерируется исключение NoSuchMethodError.

В противном случае, если разрешённый метод является методом класса (static), инструкция invokespecial генерирует исключение IncompatibleClassChangeError.

Исключения времени выполнения

В противном случае, если objectref является null, инструкция invokespecial генерирует исключение NullPointerException.

В противном случае, если этап 1, этап 2 или этап 3 процедуры поиска выбирают метод abstract, invokespecial генерирует исключение AbstractMethodError.

В противном случае, если этап 1, этап 2 или этап 3 процедуры поиска выбирают метод native и код, реализующий метод, не может быть привязан, invokespecial генерирует исключение UnsatisfiedLinkError.

В противном случае, если этап 4 процедуры поиска определяет, что существует несколько максимально специфичных методов суперинтерфейса C, которые соответствуют имени и дескриптору разрешённого метода и не являются abstract, invokespecial генерирует исключение IncompatibleClassChangeError.

В противном случае, если этап 4 процедуры поиска определяет, что не существует максимально специфичных методов суперинтерфейса C, которые соответствуют имени и дескриптору разрешённого метода и не являются abstract, invokespecial генерирует исключение AbstractMethodError.

Примечания

Разница между инструкцией invokespecial и инструкцией invokevirtual (§invokevirtual) заключается в том, что invokevirtual вызывает метод, основанный на классе объекта. Инструкция invokespecial используется для прямого вызова методов инициализации экземпляров (§2.9.1), а также методов текущего класса и его супертипов.

Инструкция invokespecial называлась invokenonvirtual до выпуска JDK 1.0.2.

Значения аргумента nargs и objectref не соответствуют локальным переменным в порядке следования. Значения аргументов типов long и double должны храниться в двух последовательных локальных переменных, поэтому для передачи nargs значений аргументов вызываемому методу может потребоваться больше, чем nargs локальных переменных.

Инструкция invokespecial обрабатывает вызов не-abstract метода интерфейса, на который ссылаются либо непосредственно через суперинтерфейс, либо через суперкласс. В этих случаях правила выбора в основном такие же, как и для invokeinterface (за исключением того, что поиск начинается с другого класса).

invokestatic

Операция

Вызов метода класса (static)

Формат


invokestatic
indexbyte1
indexbyte2

Формы

invokestatic = 184 (0xb8)

Оперативная память стека

..., [arg1, [arg2 ...]] →

...

Описание

Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения по этому индексу должен быть символьной ссылкой на метод или метод интерфейса (§5.1), которая указывает имя и дескриптор (§4.3.3) метода или метода интерфейса, а также символьной ссылкой на класс или интерфейс, в котором находится метод или метод интерфейса. Названный метод разрешается (§5.4.3.3, §5.4.3.4).

Разрешенный метод не должен быть методом инициализации экземпляра или методом инициализации класса или интерфейса (§2.9.1, §2.9.2).

Разрешенный метод должен быть static, и поэтому не может быть abstract.

При успешном разрешении метода класс или интерфейс, который объявил разрешенный метод, инициализируется, если этот класс или интерфейс еще не были инициализированы (§5.5).

Оперативная память стека должна содержать nargs значений аргументов, где количество, тип и порядок значений должны соответствовать дескриптору разрешенного метода.

Если метод является synchronized, монитор, связанный с разрешенным Class объектом, вводится или повторно вводится как при выполнении инструкции monitorenter (§monitorenter) в текущем потоке.

Если метод не является native, nargs значений аргументов извлекаются из оперативной памяти стека. В стеке виртуальной машины Java создается новый фрейм для вызываемого метода. nargs значений аргументов последовательно становятся значениями локальных переменных нового фрейма, с arg1 в локальной переменной 0 (или, если arg1 имеет тип long или double, в локальных переменных 0 и 1) и так далее. Новый фрейм затем становится текущим, и виртуальная машина Java устанавливается в код первой инструкции вызываемого метода. Выполнение продолжается с первой инструкции метода.

Если метод является native и зависимая от платформы кодовое реализация еще не связана (§5.6) с виртуальной машиной Java, она выполняется. nargs значений аргументов извлекаются из оперативной памяти стека и передаются в качестве параметров коду, реализующему метод. Параметры передаются, и код вызывается способом, зависящим от реализации. После возврата кода платформы происходят следующие действия:

  • Если метод native является synchronized, монитор, связанный с разрешенным Class объектом, обновляется и, возможно, выходит из него, как если бы выполнялась инструкция monitorexit (§monitorexit) в текущем потоке.

  • Если метод native возвращает значение, возвращаемое значение кода платформы преобразуется способом, зависящим от реализации, в возвращаемый тип метода native и помещается в оперативную память стека.

Исключения привязки

При разрешении символьной ссылки на метод могут быть выброшены любые исключения, связанные с разрешением метода (§5.4.3.3).

В противном случае, если разрешенный метод является методом экземпляра, инструкция invokestatic выбросит исключение IncompatibleClassChangeError.

Исключения времени выполнения

В противном случае, если выполнение этой инструкции invokestatic вызывает инициализацию указанного класса или интерфейса, invokestatic может выбросить исключение Error, как подробно описано в §5.5.

В противном случае, если разрешенный метод является native и код, реализующий метод, не может быть связан, invokestatic выбросит исключение UnsatisfiedLinkError.

Примечания

Значения аргументов nargs не являются однозначным соответствием первым nargs локальным переменным. Значения аргументов типов long и double должны храниться в двух последовательных локальных переменных, поэтому для передачи nargs значений аргументов вызываемому методу может потребоваться больше, чем nargs локальных переменных.

invokevirtual

Операция

Вызов метода экземпляра; диспетчеризация на основе класса

Формат


invokevirtual
indexbyte1
indexbyte2

Формы

invokevirtual = 182 (0xb6)

Оперативная память стека

..., objectref, [arg1, [arg2 ...]] →

...

Описание

Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения по данному индексу должен быть символической ссылкой на метод (§5.1), который предоставляет имя и дескриптор (§4.3.3) метода, а также символическую ссылку на класс, в котором находится метод. Имя метода разрешается (§5.4.3.3).

Если разрешённый метод не полиморфен по сигнатуре (§2.9.3), то инструкция invokevirtual выполняется следующим образом.

Пусть C — класс objectref. Метод выбирается относительно C и разрешённого метода (§5.4.6). Это вызываемый метод.

objectref должен следовать на стеке операндов nargs значениями аргументов, где количество, тип и порядок значений должны соответствовать дескриптору выбранного метода экземпляра.

Если вызываемый метод — synchronized, то монитор, связанный с objectref, входит в него или повторно входит в него так, как если бы он выполнял инструкцию monitorenter (§monitorenter) в текущем потоке.

Если вызываемый метод не native, то nargs значений аргументов и objectref извлекаются из стека операндов. Для вызываемого метода создаётся новая рамка на стеке виртуальной машины Java. objectref и значения аргументов последовательно становятся значениями локальных переменных новой рамки, при этом objectref находится в локальной переменной 0, arg1 — в локальной переменной 1 (или, если arg1 имеет тип long или double, в локальных переменных 1 и 2) и так далее. Новая рамка затем становится текущей, и виртуальная машина Java pc устанавливается в код операции первого набора инструкций вызываемого метода. Выполнение продолжается с первой инструкции метода.

Если вызываемый метод — native, и зависимая от платформы реализация его ещё не связана (§5.6) в виртуальную машину Java, то это делается. nargs значений аргументов и objectref извлекаются из стека операндов и передаются в качестве параметров реализации метода. Параметры передаются, и код вызывается способом, зависящим от реализации. По возвращении зависимого от платформы кода происходят следующие действия:

  • Если метод native — synchronized, монитор, связанный с objectref, обновляется и, возможно, выходит из него так, как если бы он выполнял инструкцию monitorexit (§monitorexit) в текущем потоке.

  • Если метод native возвращает значение, возвращаемое значение зависимого от платформы кода преобразуется способом, зависящим от реализации, в тип возвращаемого значения метода native и помещается на стек операндов.

Если разрешённый метод полиморфен по сигнатуре (§2.9.3), и объявлен в классе java.lang.invoke.MethodHandle, то инструкция invokevirtual выполняется следующим образом, где D — дескриптор метода, символически указанного инструкцией.

Сначала reference к экземпляру java.lang.invoke.MethodType получается так, как будто происходит разрешение символической ссылки на тип метода (§5.4.3.5) с теми же параметрами и типами возвращаемых значений, что и D.

  • Если имя метода — invokeExact, экземпляр java.lang.invoke.MethodType должен быть семантически равен описателю типа получающего дескриптора метода objectref. Обрабатываемый дескриптор метода — objectref.

  • Если имя метода — invoke, и экземпляр java.lang.invoke.MethodType семантически равен описателю типа получающего дескриптора метода objectref, тогда обрабатываемый дескриптор метода — objectref.

  • Если имя метода — invoke, и экземпляр java.lang.invoke.MethodType не семантически равен описателю типа получающего дескриптора метода objectref, виртуальная машина Java пытается скорректировать описатель типа получающего дескриптора метода, как если бы при вызове метода asType класса java.lang.invoke.MethodHandle, чтобы получить точно вызываемый дескриптор метода m. Обрабатываемый дескриптор метода — m.

objectref должен следовать на стеке операндов nargs значениями аргументов, где количество, тип и порядок значений должны соответствовать описателю типа вызываемого дескриптора метода. (Этот описатель типа будет соответствовать описателю метода, подходящему для типа дескриптора вызываемого дескриптора метода, как указано в §5.4.3.5.)

Затем, если вызываемый дескриптор метода имеет поведение байткода, виртуальная машина Java вызывает дескриптор метода как если бы он выполнялся поведением байткода, связанному с типом дескриптора метода. Если тип 5 (REF_invokeVirtual), 6 (REF_invokeStatic), 7 (REF_invokeSpecial), 8 (REF_newInvokeSpecial) или 9 (REF_invokeInterface), тогда рамка будет создана и сделана текущей в процессе выполнения поведения байткода; однако, эта рамка не отображается, и когда вызываемый методом байткод завершается (обычно или прерывисто), рамка его вызывающего метода считается рамкой для метода, содержащего эту инструкцию invokevirtual.

В противном случае, если вызываемый дескриптор метода не имеет поведения байткода, виртуальная машина Java вызывает его способом, зависящим от реализации.

Если разрешённый метод полиморфен по сигнатуре и объявлен в классе java.lang.invoke.VarHandle, то инструкция invokevirtual выполняется следующим образом, где N и D — имя и дескриптор метода, символически указанного инструкцией.

Сначала reference к экземпляру java.lang.invoke.VarHandle.AccessMode получается так, как будто происходит вызов метода valueFromMethodName класса java.lang.invoke.VarHandle.AccessMode с аргументом String, обозначающим N.

Во-вторых, reference к экземпляру java.lang.invoke.MethodType получается так, как будто происходит вызов метода accessModeType класса java.lang.invoke.VarHandle по экземпляру objectref с экземпляром java.lang.invoke.VarHandle.AccessMode в качестве аргумента.

В-третьих, reference к экземпляру java.lang.invoke.MethodHandle получается так, как будто происходит вызов метода varHandleExactInvoker класса java.lang.invoke.MethodHandles с экземпляром java.lang.invoke.VarHandle.AccessMode в качестве первого аргумента и экземпляром java.lang.invoke.MethodType в качестве второго аргумента. Результирующий экземпляр называется дескриптором вызываемого метода.

Наконец, nargs значений аргументов и objectref извлекаются из стека операндов, и вызываемый дескриптор метода вызывается. Вызов происходит так, как если бы выполнялась инструкция invokevirtual, которая указывает на индекс пула постоянных времени выполнения на символическую ссылку R, где:

  • R — это символическая ссылка на метод класса;

  • для символической ссылки на класс, в котором должен находиться метод, R указывает java.lang.invoke.MethodHandle;

  • для имени метода, R указывает invoke;

  • для описателя метода, R указывает тип возвращаемого значения, обозначенный возвращающим описателем D, и указывает тип первого параметра java.lang.invoke.VarHandle, за которым следуют типы параметров, обозначенные параметрами описателей D (если таковые имеются) в порядке следования.

и где происходит как если бы следующие элементы были добавлены в стек операндов в порядке:

  • ссылка на экземпляр reference к экземпляру java.lang.invoke.MethodHandle (обработчик метода-вызываемого);

  • objectref;

  • значения аргументов nargs, где количество, тип и порядок значений должны соответствовать описателю типа обработчика метода-вызываемого.

Исключения связывания

Во время разрешения символической ссылки на метод могут быть выброшены любые исключения, относящиеся к разрешению методов (§5.4.3.3).

В противном случае, если разрешенный метод является методом класса (static), инструкция invokevirtual выбрасывает исключение IncompatibleClassChangeError.

В противном случае, если разрешенный метод является полиморфным по сигнатуре и объявлен в классе java.lang.invoke.MethodHandle, то во время разрешения типа метода, полученного из описателя в символической ссылке на метод, могут быть выброшены любые исключения, связанные с разрешением типа метода (§5.4.3.5).

В противном случае, если разрешенный метод является полиморфным по сигнатуре и объявлен в классе java.lang.invoke.VarHandle, то может быть выброшено любое исключение связывания, которое может возникнуть при вызове обработчика метода-вызываемого. Никакие исключения связывания не выбрасываются при вызове методов valueFromMethodName, accessModeType и varHandleExactInvoker.

Исключения времени выполнения

В противном случае, если objectref имеет значение null, инструкция invokevirtual выбрасывает исключение NullPointerException.

В противном случае, если разрешенный метод не является полиморфным по сигнатуре:

  • Если выбранный метод имеет значение abstract, invokevirtual выбрасывает исключение AbstractMethodError.

  • В противном случае, если выбранный метод имеет значение native и код, реализующий метод, не может быть связан, invokevirtual выбрасывает исключение UnsatisfiedLinkError.

  • В противном случае, если метод не выбран, и существует несколько максимально-специфичных методов суперинтерфейса C, которые соответствуют имени и описателю разрешенного метода и не являются abstract, invokevirtual выбрасывает исключение IncompatibleClassChangeError

  • В противном случае, если метод не выбран, и нет максимально-специфичных методов суперинтерфейса C, которые соответствуют имени и описателю разрешенного метода и не являются abstract, invokevirtual выбрасывает исключение AbstractMethodError.

В противном случае, если разрешенный метод является полиморфным по сигнатуре и объявлен в классе java.lang.invoke.MethodHandle, то:

  • Если имя метода является invokeExact, и полученный экземпляр java.lang.invoke.MethodType не семантически равен описателю типа получающего обработчика метода objectref, инструкция invokevirtual выбрасывает исключение java.lang.invoke.WrongMethodTypeException.

  • Если имя метода является invoke, и полученный экземпляр java.lang.invoke.MethodType не является допустимым аргументом для метода asType класса java.lang.invoke.MethodHandle, вызываемого на получающем обработчике метода objectref, инструкция invokevirtual выбрасывает исключение java.lang.invoke.WrongMethodTypeException.

В противном случае, если разрешенный метод является полиморфным по сигнатуре и объявлен в классе java.lang.invoke.VarHandle, то любое исключение времени выполнения, которое может возникнуть при вызове обработчика метода-вызываемого, может быть выброшено. Никакие исключения времени выполнения не выбрасываются при вызове методов valueFromMethodName, accessModeType и varHandleExactInvoker, за исключением NullPointerException, если objectref имеет значение null.

Примечания

Значения аргументов nargs и objectref не являются взаимно однозначными с первыми nargs+1 локальными переменными. Значения аргументов типов long и double должны храниться в двух последовательных локальных переменных, следовательно, для передачи nargs значений аргументов вызываемому методу может потребоваться больше, чем nargs локальных переменных.

Возможна ситуация, когда символическая ссылка инструкции invokevirtual разрешается на метод интерфейса. В этом случае возможно, что в иерархии классов нет переопределенного метода, но существует метод не-abstract интерфейса, соответствующий описателю разрешенного метода. Логика выбора соответствует такому методу, используя те же правила, что и для invokeinterface.

ior

Операция

Побитовое ИЛИ int

Формат


ior

Формы

ior = 128 (0x80)

Стек операндов

..., value1, value2 →

..., result

Описание

value1 и value2 должны быть типа int. Они извлекаются из стека операндов. Вычисляется результат result взятием побитового включительно ИЛИ от value1 и value2. Результат result помещается в стек операндов.

irem

Операция

Остаток от деления int

Формат


irem

Формы

irem = 112 (0x70)

Стек операндов

..., value1, value2 →

..., result

Описание

И value1, и value2 должны быть типа int. Значения извлекаются из стека операндов. Результат result вычисляется как value1 - (value1 / value2) * value2. Результат result помещается на стек операндов.

Результат инструкции irem таков, что (a/b)*b + (a%b) равно a. Это равенство выполняется и в особом случае, когда делимое является отрицательным int наибольшего возможного значения для своего типа, а делитель равен -1 (остаток равен 0). Из этого правила следует, что результат операции остатка может быть отрицательным только в том случае, если делимое отрицательно, и может быть положительным только в том случае, если делимое положительно. Кроме того, абсолютное значение результата всегда меньше абсолютного значения делителя.

Исключение во время выполнения

Если значение делителя для оператора вычисления остатка int равно 0, irem генерирует исключение ArithmeticException.

ireturn

Операция

Возврат int из метода

Формат


ireturn

Формы

ireturn = 172 (0xac)

Стек операндов

..., value →

[пусто]

Описание

Текущий метод должен иметь тип возвращаемого значения boolean, byte, char, short или int. value должно быть типа int. Если текущий метод является методом synchronized, то монитор, на который вошла или вошла повторно нить при вызове метода, обновляется и, возможно, выходит, как если бы была выполнена инструкция monitorexit (§monitorexit) в текущей нити. Если исключение не сгенерировано, value извлекается из стека операндов текущей фрейм и помещается на стек операндов фрейма вызывающего метода. Все другие значения на стеке операндов текущего метода удаляются.

Перед помещением value в стек операндов фрейма вызывающего метода, может потребоваться его преобразование. Если тип возвращаемого значения вызываемого метода был byte, char или short, то value преобразуется из int в тип возвращаемого значения как при выполнении i2b, i2c или i2s соответственно. Если тип возвращаемого значения вызываемого метода был boolean, то value сужается с int до boolean, взяв битовую И от value и 1.

Затем интерпретатор возвращает управление вызывающему методу, восстанавливая фрейм вызывающего метода.

Исключения во время выполнения

Если реализация Java Virtual Machine не применяет правила упорядочения блокировок, описанные в §2.11.10, то если текущий метод является методом synchronized, и текущая нить не является владельцем монитора, на который вошла или вошла повторно нить при вызове метода, ireturn генерирует исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит инструкцию monitorexit, но не инструкцию monitorenter для объекта, на котором метод синхронизирован.

В противном случае, если реализация Java Virtual Machine применяет правила упорядочения блокировок, описанные в §2.11.10, и если первое из этих правил нарушено при вызове текущего метода, то ireturn генерирует исключение IllegalMonitorStateException.

ishl

Операция

Сдвиг влево int

Формат


ishl

Формы

ishl = 120 (0x78)

Стек операндов

..., value1, value2 →

..., result

Описание

И value1, и value2 должны быть типа int. Значения извлекаются из стека операндов. Результат result вычисляется сдвигом value1 влево на s позиций, где s - значение 5 младших битов value2. Результат result помещается на стек операндов.

Примечания

Это эквивалентно (даже при переполнении) умножению на 2 в степени s. Расстояние сдвига фактически используется в диапазоне от 0 до 31 включительно, как будто value2 подверглось побитовому логическому И с маской 0x1f.

ishr

Сдвиг вправо со знаком

Арифметический сдвиг вправо int

Формат


ishr

Формы

ishr = 122 (0x7a)

Стек операндов

..., value1, value2 →

..., result

Описание

Оба value1 и value2 должны быть типа int. Значения извлекаются из стека операндов. Результат result вычисляется путём сдвига value1 вправо на s бит с расширением знака, где s является значением пяти младших битов value2. Результат result помещается в стек операндов.

Примечания

Результирующее значение равно floor(value1 / 2s), где s равно value2 & 0x1f. Для неотрицательных value1 это эквивалентно усечению int деления на 2 в степени s. Расстояние сдвига, фактически используемое, всегда находится в диапазоне от 0 до 31 включительно, как если бы value2 подверглось побитовому логическому И с маской 0x1f.

istore

Операция

Сохранить int в локальной переменной

Формат


istore
index

Формы

istore = 54 (0x36)

Стек операндов

..., value →

...

Описание

index - это беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей области видимости (§2.6). value в верхней части стека операндов должен быть типа int. Он извлекается из стека операндов, а значение локальной переменной по индексу index устанавливается в value.

Примечания

Инструкция istore может использоваться совместно с инструкцией wide (§wide) для доступа к локальной переменной с помощью двухбайтового беззнакового индекса.

istore_<n>

Операция

Сохранить int в локальной переменной

Формат


istore_<n>

Формы

istore_0 = 59 (0x3b)

istore_1 = 60 (0x3c)

istore_2 = 61 (0x3d)

istore_3 = 62 (0x3e)

Стек операндов

..., value →

...

Описание

<n> - это индекс в массиве локальных переменных текущей области видимости (§2.6). Значение value в верхней части стека операндов должно быть типа int. Оно извлекается из стека операндов, а значение локальной переменной по индексу <n> устанавливается в value.

Примечания

Каждая из инструкций istore_<n> идентична инструкции istore с индексом <n>, за исключением того, что операнд <n> неявный.

isub

Операция

Вычитание int

Формат


isub

Формы

isub = 100 (0x64)

Стек операндов

..., value1, value2 →

..., result

Описание

Оба value1 и value2 должны быть типа int. Значения извлекаются из стека операндов. Результирующее значение result равно value1 - value2. Результат result помещается в стек операндов.

Для int вычитания a-b даёт тот же результат, что и a+(-b). Для int значений вычитание из нуля эквивалентно отрицанию.

Результат - 32 младших бита истинного математического результата в формате дополнения до двух достаточной ширины, представленного как значение типа int. Если происходит переполнение, то знак результата может отличаться от знака математической разницы двух значений.

Несмотря на то, что переполнение может произойти, выполнение инструкции isub никогда не генерирует исключение во время выполнения.

iushr

Операция

Логический сдвиг вправо int

Формат


iushr

Формы

iushr = 124 (0x7c)

Стек операндов

..., value1, value2 →

..., result

Описание

И value1, и value2 должны быть типа int. Значения извлекаются из стека операндов. Вычисляется значение result путем сдвига value1 вправо на s позиций бит с заполнением нулями, где s — значение пяти младших битов value2. result помещается на стек операндов.

Примечания

Если value1 положительно, а s равно value2 & 0x1f, результат будет таким же, как при сдвиге value1 вправо на s; если value1 отрицательно, результат будет равен значению выражения (value1 >> s) + (2 << ~s). Добавление члена (2 << ~s) отменяет сдвинутый знаковый бит. Используемое расстояние сдвига всегда находится в диапазоне от 0 до 31 включительно.

ixor

Операция

Побитовое XOR int

Формат


ixor

Формы

ixor = 130 (0x82)

Стек операндов

..., value1, value2 →

..., result

Описание

И value1, и value2 должны быть типа int. Они извлекаются из стека операндов. Вычисляется значение result путем побитового исключающего ИЛИ value1 и value2. result помещается на стек операндов.

jsr

Операция

Вызов подпрограммы

Формат


jsr
branchbyte1
branchbyte2

Формы

jsr = 168 (0xa8)

Стек операндов

... →

..., address

Описание

Адрес инструкции, следующей за инструкцией jsr, помещается на стек операндов как значение типа returnAddress. Беззнаковые branchbyte1 и branchbyte2 используются для построения 16-битного смещения, где смещение равно (branchbyte1 << 8) | branchbyte2. Выполнение продолжается по адресу, смещенному на это значение относительно адреса инструкции jsr. Целевой адрес должен соответствовать коду инструкции в методе, содержащем инструкцию jsr.

Примечания

Обратите внимание, что jsr помещает адрес на стек операндов, а ret (§ret) извлекает его из локальной переменной. Эта асимметрия намеренная.

В реализации компилятора Oracle для языка программирования Java до Java SE 6 инструкция jsr использовалась с инструкцией ret для реализации блока finally (§3.13, §4.10.2.5).

jsr_w

Операция

Вызов подпрограммы (широкий индекс)

Формат


jsr_w
branchbyte1
branchbyte2
branchbyte3
branchbyte4

Формы

jsr_w = 201 (0xc9)

Стек операндов

... →

..., address

Описание

Адрес инструкции, следующей за инструкцией jsr_w, помещается на стек операндов как значение типа returnAddress. Беззнаковые branchbyte1, branchbyte2, branchbyte3 и branchbyte4 используются для построения 32-битного смещения, где смещение равно (branchbyte1 << 24) | (branchbyte2 << 16) | (branchbyte3 << 8) | branchbyte4. Выполнение продолжается по адресу, смещенному на это значение относительно адреса инструкции jsr_w. Целевой адрес должен соответствовать коду инструкции в методе, содержащем инструкцию jsr_w.

Примечания

Обратите внимание, что jsr_w помещает адрес на стек операндов, а ret (§ret) извлекает его из локальной переменной. Эта асимметрия намеренная.

В реализации компилятора Oracle для языка программирования Java до Java SE 6 инструкция jsr_w использовалась с инструкцией ret для реализации блока finally (§3.13, §4.10.2.5).

Несмотря на то, что инструкция jsr_w использует 4-байтовое смещение ветвления, другие факторы ограничивают размер метода до 65535 байт (§4.11). Это ограничение может быть увеличено в будущих версиях Java Virtual Machine.

l2d

Операция

Преобразовать long в double

Формат


l2d

Формы

l2d = 138 (0x8a)

Стек операндов

..., value →

..., result

Описание

Значение value вверху стека операндов должно быть типа long. Оно извлекается из стека операндов и преобразуется в result типа double с использованием правила округления до ближайшего значения (§2.8). Значение result помещается в стек операндов.

Примечания

Инструкция l2d выполняет расширяющее преобразование примитивного типа (JLS §5.1.2), которое может привести к потере точности, так как значения типа double имеют только 53 бита мантиссы.

l2f

Операция

Преобразовать long в float

Формат


l2f

Формы

l2f = 137 (0x89)

Стек операндов

..., value →

..., result

Описание

Значение value вверху стека операндов должно быть типа long. Оно извлекается из стека операндов и преобразуется в result типа float с использованием правила округления до ближайшего значения (§2.8). Значение result помещается в стек операндов.

Примечания

Инструкция l2f выполняет расширяющее преобразование примитивного типа (JLS §5.1.2), которое может привести к потере точности, так как значения типа float имеют только 24 бита мантиссы.

l2i

Операция

Преобразовать long в int

Формат


l2i

Формы

l2i = 136 (0x88)

Стек операндов

..., value →

..., result

Описание

Значение value вверху стека операндов должно быть типа long. Оно извлекается из стека операндов и преобразуется в result типа int, взяв младшие 32 бита значения long и отбросив старшие 32 бита. Значение result помещается в стек операндов.

Примечания

Инструкция l2i выполняет сужающее преобразование примитивного типа (JLS §5.1.3). Она может потерять информацию о значении value в целом. Значение result также может иметь другой знак, чем value.

ladd

Операция

Сложить long

Формат


ladd

Формы

ladd = 97 (0x61)

Стек операндов

..., value1, value2 →

..., result

Описание

Оба значения value1 и value2 должны быть типа long. Значения извлекаются из стека операндов. Результат result типа long вычисляется как value1 + value2. Результат помещается в стек операндов.

Результат — это 64 младших бита истинного математического результата в формате с достаточно большой разрядностью дополнения до двух, представленного в виде значения типа long. Если происходит переполнение, знак результата может не совпадать со знаком математической суммы двух значений.

Несмотря на то, что может произойти переполнение, выполнение инструкции ladd никогда не вызывает исключения во время выполнения.

laload

Операция

Загрузка long из массива

Формат


laload

Формы

laload = 47 (0x2f)

Стек операндов

..., arrayref, index →

..., value

Описание

Значение arrayref должно быть типа reference и должно ссылаться на массив, компоненты которого имеют тип long. Значение index должно быть типа int. Оба значения arrayref и index извлекаются из стека операндов. Значение value в компоненте массива по индексу index извлекается и помещается в стек операндов.

Исключения во время выполнения

Если arrayref является null, инструкция laload вызывает исключение NullPointerException.

В противном случае, если index не находится в пределах границ массива, на который ссылается arrayref, инструкция laload вызывает исключение ArrayIndexOutOfBoundsException.

land

Логическое И

Булево И long

Формат


land

Формы

land = 127 (0x7f)

Стек операндов

..., value1, value2 →

..., result

Описание

Оба value1 и value2 должны быть типа long. Они извлекаются из стека операндов. Вычисляется результат result побитовым И value1 и value2. Результат result помещается в стек операндов.

lastore

Операция

Запись в массив long

Формат


lastore

Формы

lastore = 80 (0x50)

Стек операндов

..., arrayref, index, value →

...

Описание

arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип long. index должен быть типа int, а value — типа long. arrayref, index и value извлекаются из стека операндов. Значение value записывается в компонент массива с индексом index.

Исключения во время выполнения

Если arrayref является null, lastore генерирует исключение NullPointerException.

В противном случае, если index выходит за пределы массива, ссылаемого на arrayref, инструкция lastore генерирует исключение ArrayIndexOutOfBoundsException.

lcmp

Операция

Сравнение long

Формат


lcmp

Формы

lcmp = 148 (0x94)

Стек операндов

..., value1, value2 →

..., result

Описание

Оба value1 и value2 должны быть типа long. Они извлекаются из стека операндов, и выполняется сравнение целых чисел со знаком. Если value1 больше value2, в стек операндов помещается значение 1. Если value1 равно value2, в стек операндов помещается значение 0. Если value1 меньше value2, в стек операндов помещается значение -1.

lconst_<l>

Операция

Поместить long константу

Формат


lconst_<l>

Формы

lconst_0 = 9 (0x9)

lconst_1 = 10 (0xa)

Стек операндов

... →

..., <l>

Описание

Поместить long константу <l> (0 или 1) в стек операндов.

ldc

Операция

Положить элемент из постоянного пула времени выполнения

Формат


ldc
индекс

Формы

ldc = 18 (0x12)

Стек операндов

... →

..., значение

Описание

Индекс — это беззнаковый байт, который должен быть допустимым индексом в постоянном пуле времени выполнения текущего класса (§2.5.5). Элемент постоянного пула времени выполнения по индексу должен быть загружаемым (§5.1), и не должен быть ни одним из следующих:

  • Численное значение типа long или double.

  • Символическая ссылка на динамически вычисляемое значение, у которого полевой дескриптор является J (обозначающее long) или D (обозначающее double).

Если элемент постоянного пула времени выполнения является числовым значением типа int или float, то значение этого числового значения помещается в стек операндов как int или float соответственно.

В противном случае, если элемент постоянного пула времени выполнения является строковым значением, то есть ссылкой на экземпляр класса String, то значение, ссылка на этот экземпляр, помещается в стек операндов.

В противном случае, если элемент постоянного пула времени выполнения является символической ссылкой на класс или интерфейс, то указанный класс или интерфейс разрешаются (§5.4.3.1), и значение, ссылка на объект, представляющий этот класс или интерфейс, помещается в стек операндов.

В противном случае, элемент постоянного пула времени выполнения является символической ссылкой на тип метода, дескриптор метода или динамически вычисляемое значение. Символическая ссылка разрешается (§5.4.3.5, §5.4.3.6), и значение, результат разрешения, помещается в стек операндов.

Исключения привязки

Во время разрешения символической ссылки могут быть выброшены любые исключения, связанные с разрешением этого типа символической ссылки.

ldc_w

Операция

Положить элемент из постоянного пула времени выполнения (широкий индекс)

Формат


ldc_w
indexbyte1
indexbyte2

Формы

ldc_w = 19 (0x13)

Стек операндов

... →

..., значение

Описание

Беззнаковые indexbyte1 и indexbyte2 собираются в беззнаковый 16-битный индекс в постоянный пул времени выполнения текущего класса (§2.5.5), где значение индекса вычисляется как (indexbyte1 << 8) | indexbyte2. Индекс должен быть допустимым индексом в постоянном пуле времени выполнения текущего класса. Элемент постоянного пула времени выполнения по этому индексу должен быть загружаемым (§5.1), и не должен быть ни одним из следующих:

  • Численное значение типа long или double.

  • Символическая ссылка на динамически вычисляемое значение, у которого полевой дескриптор является J (обозначающее long) или D (обозначающее double).

Если элемент постоянного пула времени выполнения является числовым значением типа int или float, или строковым значением, то значение определяется и помещается в стек операндов в соответствии с правилами, заданными для инструкции ldc.

В противном случае, элемент постоянного пула времени выполнения является символической ссылкой на класс, интерфейс, тип метода, дескриптор метода или динамически вычисляемое значение. Он разрешается, и значение определяется и помещается в стек операндов в соответствии с правилами, заданными для инструкции ldc.

Исключения привязки

Во время разрешения символической ссылки могут быть выброшены любые исключения, связанные с разрешением этого типа символической ссылки.

Примечания

Инструкция ldc_w идентична инструкции ldc (§ldc) за исключением более широкого индекса постоянного пула времени выполнения.

ldc2_w

Операция

Положить long или double из пула постоянных времени выполнения (широкий индекс)

Формат


ldc2_w
indexbyte1
indexbyte2

Формы

ldc2_w = 20 (0x14)

Стек операндов

... →

..., value

Описание

Беззнаковые indexbyte1 и indexbyte2 собираются в беззнаковый 16-битный индекс в пул постоянных времени выполнения текущего класса (§2.5.5), где значение индекса вычисляется как (indexbyte1 << 8) | indexbyte2. Индекс должен быть допустимым индексом в пул постоянных времени выполнения текущего класса. Запись в пуле постоянных времени выполнения по этому индексу должна быть загружаемой (§5.1), и, в частности, одной из следующих:

  • Численная константа типа long или double.

  • Символическая ссылка на динамически вычисляемую константу, описание поля которой является J (обозначающей long) или D (обозначающей double).

Если запись в пуле постоянных времени выполнения — это числовая константа типа long или double, то значение value этой числовой константы помещается в стек операндов как long или double соответственно.

В противном случае запись в пуле постоянных времени выполнения — это символическая ссылка на динамически вычисляемую константу. Символическая ссылка разрешается (§5.4.3.6) и value, результат разрешения, помещается в стек операндов.

Исключения связывания

Во время разрешения символической ссылки на динамически вычисляемую константу могут быть выброшены любые исключения, относящиеся к разрешению динамически вычисляемых констант.

Примечания

Существует только версия инструкции ldc2_w с широким индексом; нет инструкции ldc2, которая помещает long или double с однобайтовым индексом.

ldiv

Операция

Деление long

Формат


ldiv

Формы

ldiv = 109 (0x6d)

Стек операндов

..., value1, value2 →

..., result

Описание

И value1, и value2 должны быть типа long. Значения извлекаются из стека операндов. Результат result — это значение выражения языка программирования Java value1 / value2. Результат result помещается в стек операндов.

Деление по правилам Java округляется к нулю; т. е., частное, полученное для значений n / d — это значение q с модулем как можно большим при условии |d ⋅ q| ≤ |n|. Кроме того, q является положительным, когда |n| ≥ |d| и n и d имеют один знак, но q является отрицательным, когда |n| ≥ |d| и n и d имеют разные знаки.

Существует один особый случай, который не соответствует этому правилу: если делимое — это наибольшее по модулю отрицательное целое число типа long, а делитель — -1, то происходит переполнение, и результат равен делимому; несмотря на переполнение, в этом случае исключение не выбрасывается.

Исключение времени выполнения

Если значение делителя при делении long равно 0, ldiv выбрасывает исключение ArithmeticException.

lload

Операция

Загрузка long из локальной переменной

Формат


lload
index

Формы

lload = 22 (0x16)

Стек операндов

... →

..., value

Описание

index — это беззнаковый байт. И index, и index+1 должны быть индексами в массив локальных переменных текущей рамки (§2.6). Локальная переменная по индексу index должна содержать long. Значение локальной переменной по индексу index помещается в стек операндов.

Примечания

Инструкция lload может использоваться совместно с инструкцией wide (§wide) для доступа к локальной переменной с использованием двубайтового беззнакового индекса.

END_OF_DOCUMENT_MARKER

lload_<n>

Операция

Загрузка long из локальной переменной

Формат


lload_<n>

Формы

lload_0 = 30 (0x1e)

lload_1 = 31 (0x1f)

lload_2 = 32 (0x20)

lload_3 = 33 (0x21)

Операционная стопка

... →

..., значение

Описание

И <n>, и <n>+1 должны быть индексами в массиве локальных переменных текущей фрейма (§2.6). Локальная переменная в <n> должна содержать long. Значение локальной переменной в <n> помещается на операционную стопку.

Примечания

Каждая из инструкций lload_<n> такая же, как lload с индексом <n>, за исключением того, что операнд <n> неявный.

lmul

Операция

Умножение long

Формат


lmul

Формы

lmul = 105 (0x69)

Операционная стопка

..., значение1, значение2 →

..., результат

Описание

И значение1, и значение2 должны быть типа long. Эти значения извлекаются из операционной стопки. long результат равен значение1 * значение2. Результат помещается на операционную стопку.

Результат — это 64 младших бита истинного математического результата в достаточно широком формате дополнения до двух, представленного как значение типа long. Если произошел переполнение, знак результата может не совпадать со знаком математического умножения двух значений.

Несмотря на то, что переполнение может произойти, выполнение инструкции lmul никогда не генерирует исключение во время выполнения.

lneg

Операция

Отрицание long

Формат


lneg

Формы

lneg = 117 (0x75)

Операционная стопка

..., значение →

..., результат

Описание

Значение должно быть типа long. Оно извлекается из операционной стопки. long результат — арифметическое отрицание значения, -значение. Результат помещается на операционную стопку.

Для long значений, отрицание эквивалентно вычитанию из нуля. Поскольку Java Virtual Machine использует представление целых чисел в формате дополнения до двух, и диапазон значений дополнения до двух несимметричен, отрицание максимального отрицательного long приводит к тому же максимальному отрицательному числу. Несмотря на то, что переполнение произошло, исключение не генерируется.

Для всех long значений x, -x равно (~x)+1.

lookupswitch

Операция

Обращение к таблице переходов по совпадению ключа и переход

Формат


lookupswitch
<0-3 байта заполнения>
defaultbyte1
defaultbyte2
defaultbyte3
defaultbyte4
npairs1
npairs2
npairs3
npairs4
пары соответствие-смещение...

Формы

lookupswitch = 171 (0xab)

Операционная Стек

..., ключ →

...

Описание

Инструкция lookupswitch имеет переменную длину. Сразу после кода операции lookupswitch от 0 до 3 байт должны быть заполнителем, так что defaultbyte1 начинается по адресу, кратному 4 байтам от начала текущего метода (кода операции его первой инструкции). Сразу после заполнения следуют ряд знаковых 32-битных значений: default, npairs, а затем npairs пар знаковых 32-битных значений. npairs должно быть больше или равно 0. Каждая из npairs пар состоит из int соответствие и знакового 32-битного смещения. Каждое из этих знаковых 32-битных значений строится из четырёх беззнаковых байтов как (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4.

Таблица соответствие-смещение пар инструкции lookupswitch должна быть отсортирована по возрастанию соответствие.

Ключ должен быть типа int и извлекается из стека операндов. Ключ сравнивается со значениями соответствие. Если он равен одному из них, то адрес назначения вычисляется путем добавления соответствующего смещения к адресу кода операции этой инструкции lookupswitch. Если ключ не совпадает ни с одним из значений соответствие, адрес назначения вычисляется путем добавления default к адресу кода операции этой инструкции lookupswitch. Выполнение затем продолжается по адресу назначения.

Адрес назначения, который может быть рассчитан по смещению каждой пары соответствие-смещение, а также по вычисленному из default, должен быть адресом кода операции инструкции в методе, который содержит эту инструкцию lookupswitch.

Примечания

Требуемая выравнивание 4-байтовых операндов инструкции lookupswitch гарантирует выравнивание этих операндов на 4 байта тогда и только тогда, когда метод, который содержит lookupswitch, расположен на границе 4 байт.

Пары соответствие-смещение отсортированы для поддержки процедур поиска, которые быстрее, чем линейный поиск.

lor

Операция

Логическое ИЛИ long

Формат


lor

Формы

lor = 129 (0x81)

Операционная Стек

..., value1, value2 →

..., результат

Описание

Оба value1 и value2 должны быть типа long. Они извлекаются из стека операндов. long результат вычисляется путем побитового включительно ИЛИ value1 и value2. результат помещается в стек операндов.

lrem

Операция

Остаток long

Формат


lrem

Формы

lrem = 113 (0x71)

Операционная Стек

..., value1, value2 →

..., результат

Описание

Оба value1 и value2 должны быть типа long. Значения извлекаются из стека операндов. long результат – это value1 - (value1 / value2) * value2. результат помещается в стек операндов.

Результат инструкции lrem таков, что (a/b)*b + (a%b) равно a. Это равенство выполняется даже в особом случае, когда делимое является отрицательным long наибольшего возможного значения для его типа, а делитель – -1 (остаток равен 0). Из этого правила следует, что результат операции остатка может быть отрицательным только если делимое отрицательное и может быть положительным только если делимое положительное; более того, величина результата всегда меньше величины делителя.

Исключение во время выполнения

Если значение делителя для оператора остатка long равно 0, lrem генерирует исключение ArithmeticException.

lreturn

Операция

Возврат long из метода

Формат


lreturn

Формы

lreturn = 173 (0xad)

Стек операндов

..., value →

[пустой]

Описание

Текущий метод должен иметь возвращаемый тип long. Значение value должно быть типа long. Если текущий метод является методом synchronized, монитор, вошедший или повторно вошедший при вызове метода, обновляется и, возможно, выходит, как будто выполняется инструкция monitorexit (§monitorexit) в текущей нити. Если исключение не выбрасывается, value извлекается из стека операндов текущей рамки (§2.6) и помещается в стек операндов рамки вызывающего метода. Все остальные значения в стеке операндов текущего метода удаляются.

Затем интерпретатор возвращает управление вызывающему методу, восстанавливая рамку вызывающего метода.

Исключения во время выполнения

Если реализация Java Virtual Machine не выполняет правила структурированной блокировки, описанные в §2.11.10, то если текущий метод является методом synchronized, а текущая нить не является владельцем монитора, вошедшего или повторно вошедшего при вызове метода, lreturn сбрасывает исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит инструкцию monitorexit, но не инструкцию monitorenter, по объекту, на котором метод synchronized.

В противном случае, если реализация Java Virtual Machine выполняет правила структурированной блокировки, описанные в §2.11.10, и если первое из этих правил нарушается во время вызова текущего метода, то lreturn сбрасывает исключение IllegalMonitorStateException.

lshl

Операция

Сдвиг влево long

Формат


lshl

Формы

lshl = 121 (0x79)

Стек операндов

..., value1, value2 →

..., result

Описание

value1 должно быть типа long, а value2 – типа int. Значения извлекаются из стека операндов. Вычисляется long result путем сдвига value1 влево на s разрядов, где s – 6 младших разрядов value2. Значение result помещается в стек операндов.

Примечания

Это эквивалентно (даже при переполнении) умножению на 2 в степени s. Расстояние сдвига фактически используется в диапазоне от 0 до 63 включительно, как будто value2 подверглось побитовому логическому И с маской 0x3f.

lshr

Операция

Арифметический сдвиг вправо long

Формат


lshr

Формы

lshr = 123 (0x7b)

Стек операндов

..., value1, value2 →

..., result

Описание

value1 должно быть типа long, а value2 – типа int. Значения извлекаются из стека операндов. Вычисляется long result путем сдвига value1 вправо на s разрядов со знаком расширения, где s – значение 6 младших разрядов value2. Значение result помещается в стек операндов.

Примечания

Результирующее значение равно floor(value1 / 2s), где s равно value2 & 0x3f. Для неотрицательного value1 это эквивалентно усечению long деления на 2 в степени s. Расстояние сдвига фактически используется в диапазоне от 0 до 63 включительно, как будто value2 подверглось побитовому логическому И с маской 0x3f.

lstore

Операция

Сохранение long в локальную переменную

Формат


lstore
index

Формы

lstore = 55 (0x37)

Стек операндов

..., value →

...

Описание

index – беззнаковый байт. И index, и index+1 должны быть индексами в массив локальных переменных текущей рамки (§2.6). value в верхней части стека операндов должно быть типа long. Оно извлекается из стека операндов, а локальные переменные по индексам index и index+1 устанавливаются в value.

Примечания

Команда lstore может использоваться совместно с инструкцией wide (§wide) для доступа к локальной переменной с помощью двубайтового беззнакового индекса.

lstore_

Операция

Сохранение long в локальную переменную

Формат


lstore_

Формы

lstore_0 = 63 (0x3f)

lstore_1 = 64 (0x40)

lstore_2 = 65 (0x41)

lstore_3 = 66 (0x42)

Стек операндов

..., значение →

...

Описание

И <n>, и <n>+1 должны быть индексами в массиве локальных переменных текущей рамки (§2.6). Значение в верхней части стека операндов должно быть типа long. Оно извлекается из стека операндов, а локальные переменные по индексам <n> и <n>+1 устанавливаются в значение.

Примечания

Каждая из инструкций lstore_ идентична инструкции lstore с индексом <n>, за исключением того, что операнд <n> неявный.

lsub

Операция

Вычитание long

Формат


lsub

Формы

lsub = 101 (0x65)

Стек операндов

..., значение1, значение2 →

..., результат

Описание

И значение1, и значение2 должны быть типа long. Значения извлекаются из стека операндов. Результат вычисления равен значение1 - значение2. Результат помещается в стек операндов.

Для вычитания long, a-b даёт тот же результат, что и a+(-b). Для значений long, вычитание из нуля равно отрицанию.

Результат — это 64 младших бита истинного математического результата в достаточно широком формате дополнения до двух, представленного в виде значения типа long. Если происходит переполнение, знак результата может не совпадать со знаком математической разницы двух значений.

Несмотря на то, что может произойти переполнение, выполнение инструкции lsub никогда не генерирует исключение во время выполнения.

lushr

Операция

Логический сдвиг вправо long

Формат


lushr

Формы

lushr = 125 (0x7d)

Стек операндов

..., значение1, значение2 →

..., результат

Описание

Значение1 должно быть типа long, а значение2 — типа int. Значения извлекаются из стека операндов. Вычисляется результат путём логического сдвига значение1 вправо на s разрядов со знаком, заполнением нулями, где s — значение 6 младших битов значение2. Результат помещается в стек операндов.

Примечания

Если значение1 положительно, а s равно значение2 & 0x3f, результат тот же, что и у значение1 >> s; если значение1 отрицательно, результат равен значению выражения (значение1 >> s) + (2L << ~s). Добавление члена (2L << ~s) отменяет распространение знака. Расстояние сдвига, фактически используемое, всегда находится в диапазоне от 0 до 63 включительно.

lxor

Операция

Булево XOR long

Формат


lxor

Формы

lxor = 131 (0x83)

Стек операндов

..., значение1, значение2 →

..., результат

Описание

И значение1, и значение2 должны быть типа long. Они извлекаются из стека операндов. Результат вычисляется путём побитового исключающего ИЛИ значение1 и значение2. Результат помещается в стек операндов.

monitorenter

Операция

Вход в монитор объекта

Формат


monitorenter

Формы

monitorenter = 194 (0xc2)

Стек операндов

..., objectref →

...

Описание

objectref должен быть типа reference.

Каждый объект связан с монитором. Монитор заблокирован тогда и только тогда, когда у него есть владелец. Поток, выполняющий monitorenter, пытается получить владение монитором, связанным с objectref, следующим образом:

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

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

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

Исключение во время выполнения

Если objectref является null, monitorenter генерирует исключение NullPointerException.

Примечания

Инструкция monitorenter может использоваться с одной или несколькими инструкциями monitorexit (§monitorexit) для реализации оператора `synchronized` в языке программирования Java (§3.14). Инструкции monitorenter и monitorexit не используются в реализации методов, использующих блокировку synchronized, хотя их можно использовать для обеспечения эквивалентной семантики блокировки. Вход в монитор при вызове метода synchronized и выход из монитора при его возвращении обрабатываются неявно механизмом вызова и возврата метода Java Virtual Machine, как если бы использовались monitorenter и monitorexit.

Связь монитора с объектом может управляться различными способами, которые выходят за рамки данной спецификации. Например, монитор может быть выделен и освобождён одновременно с объектом. В качестве альтернативы, он может быть динамически выделен в момент попытки потока получить эксклюзивный доступ к объекту и освобождён в какой-либо момент в будущем, когда в мониторе для объекта больше нет потоков.

Конструкции синхронизации языка программирования Java требуют поддержки операций с мониторами помимо входа и выхода. К ним относятся ожидание на мониторе (Object.wait) и уведомление других потоков, ожидающих на мониторе (Object.notifyAll и Object.notify). Эти операции поддерживаются в стандартном пакете java.lang, поставляемом с Java Virtual Machine. В наборе инструкций Java Virtual Machine явной поддержки этих операций нет.

monitorexit

Операция

Выход из монитора объекта

Формат


monitorexit

Формы

monitorexit = 195 (0xc3)

Стек операндов

..., objectref →

...

Описание

objectref должен быть типа reference.

Поток, выполняющий monitorexit, должен быть владельцем монитора, связанного с экземпляром, на который ссылается objectref.

Поток декрементирует счётчик входов в монитор, связанный с objectref. Если в результате значение счётчика равно нулю, поток выходит из монитора и больше не является его владельцем. Другие потоки, блокированные для входа в монитор, могут попытаться сделать это.

Исключения во время выполнения

Если objectref является null, monitorexit генерирует исключение NullPointerException.

В противном случае, если поток, выполняющий monitorexit, не является владельцем монитора, связанного с экземпляром, на который ссылается objectref, monitorexit генерирует исключение IllegalMonitorStateException.

В противном случае, если реализация Java Virtual Machine выполняет правила структурированной блокировки, описанные в §2.11.10, и если второе из этих правил нарушается выполнением этой инструкции monitorexit, то monitorexit генерирует исключение IllegalMonitorStateException.

Примечания

Одна или несколько инструкций monitorexit могут использоваться с инструкцией monitorenter (§monitorenter) для реализации оператора `synchronized` в языке программирования Java (§3.14). Инструкции monitorenter и monitorexit не используются в реализации методов, использующих блокировку synchronized, хотя их можно использовать для обеспечения эквивалентной семантики блокировки.

Java Virtual Machine поддерживает исключения, генерируемые внутри методов synchronized и операторов synchronized по-разному:

  • Выход из монитора при нормальном завершении метода synchronized обрабатывается инструкциями возврата Java Virtual Machine. Выход из монитора при внезапном завершении метода synchronized обрабатывается неявно инструкцией athrow Java Virtual Machine.

  • Когда исключение генерируется внутри оператора synchronized, выход из монитора, в который вошли до выполнения оператора synchronized, достигается с помощью механизма обработки исключений Java Virtual Machine (§3.14).

multianewarray

Операция

Создание многомерного массива

Формат


multianewarray
indexbyte1
indexbyte2
dimensions

Формы

multianewarray = 197 (0xc5)

Стек операндов

..., count1, [count2, ...] →

..., arrayref

Описание

Операнд dimensions — это беззнаковый байт, который должен быть больше или равен 1. Он представляет количество измерений создаваемого массива. Стек операндов должен содержать dimensions значений. Каждое такое значение представляет количество компонентов в измерении создаваемого массива, должно быть типа int и должно быть неотрицательным. count1 — желаемая длина первого измерения, count2 — во втором и т. д.

Все значения count извлекаются со стека операндов. Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на класс, массив или тип интерфейса. Названный класс, массив или тип интерфейса разрешаются (§5.4.3.1). Результирующий элемент должен быть типом класса массива размерностью, большей или равной dimensions.

Новый многомерный массив указанного типа выделяется из кучи сборки мусора. Если какое-либо значение count равно нулю, последующие измерения не выделяются. Компоненты массива в первом измерении инициализируются подмассивами типа второго измерения и так далее. Компоненты последнего выделенного измерения массива инициализируются значением по умолчанию (§2.3, §2.4) для типа элемента типа массива. Ссылка arrayref на новый массив помещается на стек операндов.

Исключения при связывании

При разрешении символической ссылки на класс, массив или тип интерфейса могут быть выброшены любые исключения, описанные в §5.4.3.1.

В противном случае, если у текущего класса нет разрешения на доступ к типу элемента разрешенного класса массива, multianewarray выбросит исключение IllegalAccessError.

Исключение во время выполнения

В противном случае, если какое-либо из значений dimensions на стеке операндов меньше нуля, инструкция multianewarray выбросит исключение NegativeArraySizeException.

Примечания

Для создания массива одного измерения может быть эффективнее использовать инструкции newarray или anewarray (§newarray, §anewarray).

Класс массива, на который ссылаются через постоянный пул времени выполнения, может иметь больше измерений, чем операнд dimensions инструкции multianewarray. В этом случае создаются только первые dimensions измерений массива.

new

Операция

Создание нового объекта

Формат


new
indexbyte1
indexbyte2

Формы

new = 187 (0xbb)

Стек операндов

... →

..., objectref

Описание

Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на класс или тип интерфейса. Названный класс или тип интерфейса разрешаются (§5.4.3.1) и должны привести к типу класса. Память для нового экземпляра этого класса выделяется из кучи сборки мусора, а переменные экземпляра нового объекта инициализируются их значениями по умолчанию (§2.3, §2.4). Ссылка objectref на экземпляр помещается на стек операндов.

При успешном разрешении класса, он инициализируется, если он еще не был инициализирован (§5.5).

Исключения при связывании

При разрешении символической ссылки на класс или тип интерфейса могут быть выброшены любые исключения, описанные в §5.4.3.1.

В противном случае, если символическая ссылка на класс или тип интерфейса разрешается на интерфейс или абстрактный класс, new выбросит исключение abstract.

Исключение во время выполнения

В противном случае, если выполнение этой инструкции new приводит к инициализации ссылаемого класса, new может выбросить исключение Error, как подробно описано в JLS §15.9.4.

Примечания

Инструкция new не полностью создает новый экземпляр; создание экземпляра не завершается до тех пор, пока метод инициализации экземпляра (§2.9.1) не будет вызван для неинициализированного экземпляра.

newarray

Операция

Создать новый массив

Формат


newarray
atype

Формы

newarray = 188 (0xbc)

Стек операндов

..., count →

..., arrayref

Описание

Значение count должно быть типа int. Оно извлекается из стека операндов. count представляет количество элементов создаваемого массива.

atype — код, указывающий тип создаваемого массива. Он должен принимать одно из следующих значений:

Таблица 6.5.newarray-A. Коды типов массивов

Тип массива atype
T_BOOLEAN 4
T_CHAR 5
T_FLOAT 6
T_DOUBLE 7
T_BYTE 8
T_SHORT 9
T_INT 10
T_LONG 11

Создается новый массив, компоненты которого имеют тип atype и длину count, выделяемый из управляемой сборкой мусора кучи. В стек операндов помещается ссылка arrayref на этот новый объект массива. Каждый элемент нового массива инициализируется стандартным начальным значением (п. §2.3, §2.4) для типа элемента типа массива.

Исключение во время выполнения

Если count меньше нуля, newarray генерирует исключение NegativeArraySizeException.

Примечания

В реализации виртуальной машины Java от Oracle массивы типа boolean (atype равно T_BOOLEAN) хранятся как массивы 8-битовых значений и обрабатываются инструкциями baload и bastore (§baload, §bastore), которые также обращаются к массивам типа byte. Другие реализации могут реализовывать упакованные boolean массивы; для доступа к этим массивам необходимо использовать инструкции baload и bastore.

nop

Операция

Ничего не делать

Формат


nop

Формы

nop = 0 (0x0)

Стек операндов

Без изменений

Описание

Ничего не делать.

pop

Операция

Извлечь значение из вершины стека операндов

Формат


pop

Формы

pop = 87 (0x57)

Стек операндов

..., value →

...

Описание

Извлекается верхнее значение из стека операндов.

Инструкцию pop нельзя использовать, если value не является значением вычислительного типа категории 1 (§2.11.1).

pop2

Операция

Извлечь одно или два значения из вершины стека операндов

Формат


pop2

Формы

pop2 = 88 (0x58)

Стек операндов

Форма 1:

..., value2, value1 →

...

где каждое из value1 и value2 является значением вычислительного типа категории 1 (§2.11.1).

Форма 2:

..., value →

...

где value — значение вычислительного типа категории 2 (§2.11.1).

Описание

Извлечь одно или два верхних значения из стека операндов.

putfield

Операция

Установка поля в объекте

Формат


putfield
indexbyte1
indexbyte2

Формы

putfield = 181 (0xb5)

Стек операндов

..., objectref, value →

...

Описание

Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения по этому индексу должен быть символической ссылкой на поле (§5.1), которое содержит имя и дескриптор поля, а также символическую ссылку на класс, в котором это поле находится. Ссылка на поле разрешается (§5.4.3.2).

Тип значения value, хранимого инструкцией putfield, должен быть совместим с дескриптором ссылающегося поля (§4.3.2). Если тип дескриптора поля является boolean, byte, char, short или int, то value должно быть int. Если тип дескриптора поля является float, long или double, то value должно быть float, long или double соответственно. Если тип дескриптора поля является типом ссылки, то value должно быть типа, совместимого с типом дескриптора поля по присваиванию (JLS §5.2). Если поле является final, оно должно быть объявлено в текущем классе, и инструкция должна находиться в методе инициализации экземпляра текущего класса (§2.9.1).

Значения value и objectref извлекаются из стека операндов.

objectref должен быть типа reference, но не типа массива.

Если value имеет тип int, а тип дескриптора поля – boolean, то значение value сужается путем взятия побитовой конъюнкции value и 1, что приводит к value'. Ссылающееся поле в objectref устанавливается в value'.

В противном случае ссылающееся поле в objectref устанавливается в value.

Исключения связывания

Во время разрешения символической ссылки на поле могут быть выброшены исключения, относящиеся к разрешению поля (§5.4.3.2).

В противном случае, если разрешенное поле является полем static, putfield выбрасывает исключение IncompatibleClassChangeError.

В противном случае, если разрешенное поле является final, оно должно быть объявлено в текущем классе, а инструкция должна находиться в методе инициализации экземпляра текущего класса. В противном случае выбрасывается исключение IllegalAccessError.

Исключение времени выполнения

В противном случае, если objectref имеет значение null, инструкция putfield выбрасывает исключение NullPointerException.

putstatic

Операция

Установить статическое поле в классе

Формат


putstatic
indexbyte1
indexbyte2

Формы

putstatic = 179 (0xb3)

Стек операндов

..., значение →

...

Описание

Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле констант времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Запись в пуле констант времени выполнения по этому индексу должна быть символической ссылкой на поле (§5.1), которая предоставляет имя и дескриптор поля, а также символическую ссылку на класс или интерфейс, в котором находится поле. Ссылка на поле разрешается (§5.4.3.2).

При успешном разрешении поля, класс или интерфейс, объявивший разрешенное поле, инициализируется, если этот класс или интерфейс еще не был инициализирован (§5.5).

Тип значение, хранимый инструкцией putstatic, должен быть совместим с дескриптором ссылкой поля (§4.3.2). Если тип дескриптора поля равен boolean, byte, char, short или int, то значение должно быть int. Если тип дескриптора поля равен float, long или double, то значение должно быть float, long или double соответственно. Если тип дескриптора поля – это тип ссылки, то значение должно быть типа, совместимого с типом дескриптора поля (JLS §5.2). Если поле является final, оно должно быть объявлено в текущем классе или интерфейсе, и инструкция должна находиться в методе инициализации класса или интерфейса текущего класса или интерфейса (§2.9.2).

значение извлекается из стека операндов.

Если значение типа int, а тип дескриптора поля – boolean, то значение сужается, вычисляя побитовую И от значение и 1, что даёт значение'. Ссылаемое поле в классе или интерфейсе устанавливается в значение'.

В противном случае, ссылка поле в классе или интерфейсе устанавливается в значение.

Исключения при связывании

При разрешении символической ссылки на поле класса или интерфейса могут быть выброшены исключения, связанные с разрешением поля (§5.4.3.2).

В противном случае, если разрешенное поле не является полем класса (class) или полем интерфейса, putstatic выбросит исключение IncompatibleClassChangeError.

В противном случае, если разрешенное поле является final, оно должно быть объявлено в текущем классе или интерфейсе, и инструкция должна находиться в методе инициализации класса или интерфейса текущего класса или интерфейса. В противном случае выброшено исключение IllegalAccessError.

Исключение во время выполнения

В противном случае, если выполнение инструкции putstatic приводит к инициализации ссылаемого класса или интерфейса, putstatic может выбросить исключение Error, как подробно описано в §5.5.

Примечания

Инструкция putstatic может быть использована только для установки значения поля интерфейса при инициализации этого поля. К полям интерфейса можно присваивать значение только один раз, при выполнении выражения инициализации переменной интерфейса во время инициализации интерфейса (§5.5, JLS §9.3.1).

ret

Операция

Возврат из подпрограммы

Формат


ret
index

Формы

ret = 169 (0xa9)

Стек операндов

Без изменений

Описание

index – это беззнаковый байт от 0 до 255 включительно. Локальная переменная по индексу index в текущей области видимости (§2.6) должна содержать значение типа returnAddress. Содержимое локальной переменной записывается в регистр виртуальной машины Java, и выполнение продолжается оттуда.

Примечания

Обратите внимание, что jsr (§jsr) помещает адрес в стек операндов, а ret извлекает его из локальной переменной. Эта асимметрия намеренная.

В реализации компилятора Oracle для языка программирования Java до Java SE 6 инструкция ret использовалась с инструкциями jsr и jsr_w (§jsr, §jsr_w) в реализации блока finally (§3.13, §4.10.2.5).

Инструкцию ret не следует путать с инструкцией return (§return). Инструкция return возвращает управление из метода вызывающему методу, не передавая ему никакого значения.

Код операции ret может использоваться совместно с инструкцией wide (§wide), чтобы получить доступ к локальной переменной с помощью двухбайтного беззнакового индекса.

return

Операция

Возвращение void из метода

Формат


return

Формы

return = 177 (0xb1)

Стек операндов

... →

[пусто]

Описание

Текущий метод должен иметь тип возвращаемого значения void. Если текущий метод является методом synchronized, монитор, введённый или повторно введённый при вызове метода, обновляется и, возможно, выходит, как если бы он выполнял инструкцию monitorexit (§monitorexit) в текущем потоке. Если исключение не возникло, любые значения в стеке операндов текущей рамки (§2.6) удаляются.

Затем интерпретатор возвращает управление вызывающему методу, восстанавливая рамку вызывающего метода.

Исключения во время выполнения

Если реализация Java Virtual Machine не выполняет правила структурированной блокировки, описанные в §2.11.10, то если текущий метод является методом synchronized, а текущий поток не является владельцем монитора, введённого или повторно введённого при вызове метода, return генерирует исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит инструкцию monitorexit, но не инструкцию monitorenter для объекта, для которого метод synchronized.

В противном случае, если реализация Java Virtual Machine выполняет правила структурированной блокировки, описанные в §2.11.10, и если первое из этих правил нарушается во время вызова текущего метода, return генерирует исключение IllegalMonitorStateException.

saload

Операция

Загрузка short из массива

Формат


saload

Формы

saload = 53 (0x35)

Стек операндов

..., arrayref, index →

..., value

Описание

arrayref должен быть типа reference и должен ссылаться на массив, компоненты которого имеют тип short. index должен быть типа int. И arrayref, и index извлекаются из стека операндов. Компонент массива по индексу index извлекается и расширяется со знаком до int value. Это value помещается в стек операндов.

Исключения во время выполнения

Если arrayref является null, saload генерирует исключение NullPointerException.

В противном случае, если index не входит в границы массива, на который ссылается arrayref, инструкция saload генерирует исключение ArrayIndexOutOfBoundsException.

sastore

Операция

Сохранение в массив short

Формат


sastore

Формы

sastore = 86 (0x56)

Стек операндов

..., arrayref, index, value →

...

Описание

arrayref должен быть типа reference и должен ссылаться на массив, компоненты которого имеют тип short. index и value должны быть типа int. arrayref, index и value извлекаются из стека операндов. Значение value усекается до short и сохраняется как компонент массива по индексу index.

Исключения во время выполнения

Если arrayref является null, sastore генерирует исключение NullPointerException.

В противном случае, если index не входит в границы массива, на который ссылается arrayref, инструкция sastore генерирует исключение ArrayIndexOutOfBoundsException.

sipush

Операция

Помещение short

Формат


sipush
byte1
byte2

Формы

sipush = 17 (0x11)

Стек операндов

... →

..., value

Описание

Непосредственные значения без знака byte1 и byte2 собираются в промежуточное short, где значение short равно (byte1 << 8) | byte2. Затем промежуточное значение расширяется со знаком до int value. Это value помещается в стек операндов.

swap

Операция

Поменять местами верхние два значения стека операндов

Формат


swap

Формы

swap = 95 (0x5f)

Стек операндов

..., value2, value1 →

..., value1, value2

Описание

Поменять местами верхние два значения в стеке операндов.

Инструкция swap не должна использоваться, если value1 и value2 не являются значениями вычислительного типа категории 1 (§2.11.1).

Примечания

Виртуальная машина Java не предоставляет инструкцию для перестановки операндов категории 2.

tableswitch

Операция

Обращение к таблице переходов по индексу и переход

Формат


tableswitch
<0-3 byte pad>
defaultbyte1
defaultbyte2
defaultbyte3
defaultbyte4
lowbyte1
lowbyte2
lowbyte3
lowbyte4
highbyte1
highbyte2
highbyte3
highbyte4
jump offsets...

Формы

tableswitch = 170 (0xaa)

Стек операндов

..., index →

...

Описание

Инструкция tableswitch имеет переменную длину. Непосредственно после кода операции tableswitch от 0 до 3 байтов должны быть зарезервированы как заполнители, чтобы defaultbyte1 начиналось по адресу, кратно четырём байтам с начала текущего метода (кода первой инструкции). Непосредственно после заполнителей находятся байты, представляющие три знаковых 32-битных значения: default, low и high. Непосредственно после них находятся байты, представляющие последовательность high - low + 1 знаковых 32-битных смещений. Значение low должно быть меньше или равно high. high - low + 1 знаковых 32-битных смещений обрабатываются как таблица переходов с нулевой базой. Каждое из этих знаковых 32-битных значений строится как (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4.

index должен быть типа int и извлекается из стека операндов. Если index меньше low или больше high, то целевой адрес вычисляется путём добавления default к адресу кода операции этой инструкции tableswitch. В противном случае извлекается смещение в позиции index - low таблицы переходов. Целевой адрес вычисляется путём добавления этого смещения к адресу кода операции этой инструкции tableswitch. Выполнение затем продолжается по целевому адресу.

Целевой адрес, который может быть вычислен по каждому смещению таблицы переходов, а также по default, должен быть адресом кода операции инструкции внутри метода, содержащего эту инструкцию tableswitch.

Примечания

Требование выравнивания 4-байтовых операндов инструкции tableswitch гарантирует выравнивание этих операндов по 4 байтам тогда и только тогда, когда метод, содержащий инструкцию tableswitch, начинается на границе 4 байтов.

wide

Операция

Расширение индекса локальной переменной на дополнительные байты

Формат 1


wide
<opcode>
indexbyte1
indexbyte2

где <opcode> — одно из значений iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore или ret

Формат 2


wide
iinc
indexbyte1
indexbyte2
constbyte1
constbyte2

Формы

wide = 196 (0xc4)

Стек операндов

Такой же, как у изменённой инструкции

Описание

Инструкция wide изменяет поведение другой инструкции. Она принимает один из двух форматов, в зависимости от изменяемой инструкции. Первый формат инструкции wide изменяет одну из инструкций iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore или ret (§iload, §fload, §aload, §lload, §dload, §istore, §fstore, §astore, §lstore, §dstore, §ret). Второй формат применяется только к инструкции iinc (§iinc).

В обоих случаях за самим кодом операции wide в скомпилированном коде следует код инструкции, которую wide изменяет. В обоих форматах за изменённым кодом следуют два беззнаковых байта indexbyte1 и indexbyte2, которые собираются в 16-битный беззнаковый индекс локальной переменной в текущей области видимости (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Вычисленный индекс должен соответствовать индексу в массиве локальных переменных текущей области видимости. Где инструкция wide изменяет инструкции lload, dload, lstore или dstore, индекс, следующий за вычисленным индексом (индекс + 1), также должен быть индексом в массиве локальных переменных. Во втором формате два беззнаковых байта constbyte1 и constbyte2 следуют за indexbyte1 и indexbyte2 в потоке кода. Эти байты также собираются в знаковое 16-битное постоянное значение, где постоянное значение равно (constbyte1 << 8) | constbyte2.

Расширенный байткод работает как обычно, за исключением использования расширенного индекса и, в случае второго формата, более широкого диапазона приращений.

Примечания

Хотя мы говорим, что wide «изменяет поведение другой инструкции», инструкция wide фактически обрабатывает байты, составляющие изменённую инструкцию, как операнды, в процессе денатурирования вложенной инструкции. В случае изменённой инструкции iinc один из логических операндов iinc даже не находится в обычном смещении от кода операции. Вложенная инструкция никогда не должна выполняться напрямую; её код операции никогда не должен быть целевым адресом никакой инструкции передачи управления.

© Oracle and/or its affiliates. All rights reserved.
Licensed under the Oracle Technology Network License Agreement.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API