Spec-Zone.ru › Java Virtual Machine Specification 7

Глава 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
if_icmp
if
ifnonnull
ifnull
iinc
iload
iload_
imul
ineg
instanceof
invokedynamic
invokeinterface
invokespecial
invokestatic
invokevirtual
ior
irem
ireturn
ishl
ishr
istore
istore_<n>
isub
iushr
ixor
jsr
jsr_w
l2d
l2f
l2i
ladd
laload
land
lastore
lcmp
lconst_<l>
ldc
ldc_w
ldc2_w
ldiv
lload
lload_<n>
lmul
lneg
lookupswitch
lor
lrem
lreturn
lshl
lshr
lstore
lstore_<n>
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. В описании отдельных инструкций виртуальной машины Java мы часто говорим, что какая-либо ситуация «должна» или «не должна» быть: «Значение value2 должно быть типа int». Ограничения §4 гарантируют, что все подобные ожидания на самом деле будут выполнены. Если какое-либо ограничение («должен» или «не должен») в описании инструкции не выполняется во время выполнения, поведение виртуальной машины Java является неопределённым.

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

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

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

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

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

END_OF_DOCUMENT_MARKER

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

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

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

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

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

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

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

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

мнемоника

Операция

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

Формат


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

Формы

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

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

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

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

Описание

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

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

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

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

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

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

Примечания

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

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

Помните, что «операнды» генерируются на этапе компиляции и встроены в инструкции виртуальной машины 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 извлекаются из стека операндов. Значение reference value в компоненте массива по index извлекается и помещается в стек операндов.

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

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

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

aastore

Операция

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

Формат


aastore

Формы

aastore = 83 (0x53)

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

..., arrayref, index, value →

...

Описание

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

Во время выполнения тип value должен быть совместим с типом компонентов массива, на который ссылается arrayref. Конкретно, присваивание значения типа ссылки S (источник) компоненту массива типа ссылки T (цель) разрешено только при выполнении следующих условий:

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

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

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

  • Если S – тип интерфейса, то:

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

    • Если T – тип интерфейса, то T должен быть тем же интерфейсом, что и S, или суперинтерфейсом S.

  • Если 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, и фактический тип value не совместим для присваивания (JLS §5.2) с фактическим типом компонентов массива, 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_

Операция

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

Формат


aload_

Формы

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_ нельзя использовать для загрузки значения типа returnAddress из локальной переменной в стек операндов. Эта асимметрия с соответствующей инструкцией astore_ (§astore_) сделана намеренно.

Каждая из инструкций aload_ эквивалентна 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 на этот новый объект массива помещается в стек операндов. Все элементы нового массива инициализируются значением null, значением по умолчанию для типов 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) массива, на который он ссылается. Эта длина помещается в стек операндов как 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), чтобы получить доступ к локальной переменной, используя двухбайтовый беззнаковый индекс.

astore_

Операция

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

Формат


astore_

Формы

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_ используется с objectref типа returnAddress при реализации положений языка программирования Java, относящихся к блокам finally (§3.13).

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

Каждая из инструкций astore_ эквивалентна инструкции 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 value и помещается на вершину стека операндов.

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

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

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

Примечания

Инструкция baload используется для загрузки значений из массивов byte и boolean. В реализации виртуальной машины Java Oracle, массивы 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 извлекаются из стека операндов. Значение value усекается до типа byte и сохраняется в качестве компонента массива по индексу 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. Это значение value помещается на стек операндов.

caload

Операция

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

Формат


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

Операция

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

Формат


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 — тип интерфейса, то:

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

    • Если T — тип интерфейса, то T должен быть тем же интерфейсом, что и S, или суперинтерфейсом S.

  • Если 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)

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

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

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

Описание

Значение значение на вершине стека операндов должно быть типа double. Оно извлекается из стека операндов и преобразуется с помощью преобразования множества значений (§2.8.3), что приводит к значение'. Затем значение' преобразуется в float результат с использованием режима округления IEEE 754 до ближайшего значения. Результат результат помещается в стек операндов.

Если инструкция d2f является FP-строгой (§2.8.2), результат преобразования всегда округляется до ближайшего представимого значения в множестве значений типа float (§2.3.2).

Если инструкция d2f не является FP-строгой, результат преобразования может быть взят из множества значений с расширенным экспонентом (§2.3.2); он не обязательно округляется до ближайшего представимого значения в множестве значений типа float.

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

Примечания

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

d2i

Операция

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

Формат


d2i

Формы

d2i = 142 (0x8e)

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

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

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

Описание

Значение значение на вершине стека операндов должно быть типа double. Оно извлекается из стека операндов и подвергается преобразованию типов значений (§2.8.3), в результате чего получается значение'. Затем значение' преобразуется в int. Результат помещается в стек операндов:

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

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

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

Примечания

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

d2l

Операция

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

Формат


d2l

Формы

d2l = 143 (0x8f)

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

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

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

Описание

Значение значение на вершине стека операндов должно быть типа double. Оно извлекается из стека операндов и подвергается преобразованию в соответствии с набором значений (§2.8.3), в результате чего получается значение'. Затем значение' преобразуется в long. Результат результат помещается в стек операндов:

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

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

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

Примечания

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

dadd

Операция

Добавить double

Формат


dadd

Формы

dadd = 99 (0x63)

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

..., value1, value2 →

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

Описание

И value1, и value2 должны быть типа double. Значения извлекаются из стека операндов и подвергаются преобразованию типов (§2.8.3), в результате чего получаются value1' и value2'. double Результат результат равен value1' + value2'. Результат результат помещается в стек операндов.

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

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

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

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

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

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

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

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

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

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

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

daload

Операция

Загрузка значения из массива

Формат


daload

Формы

daload = 49 (0x31)

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

..., arrayref, index →

..., value

Описание

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

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

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

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

dastore

Операция

Сохранение значения в массив

Формат


dastore

Формы

dastore = 82 (0x52)

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

..., arrayref, index, value →

...

Описание

arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип double. index должен быть типа int, а value — типа double. arrayref, index и value извлекаются из стека операндов. Значение value претерпевает преобразование (§2.8.3), в результате чего получается 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. Значения извлекаются из стека операндов и подвергаются преобразованию набора значений (§2.8.3), в результате чего получаются value1' и value2'. Производится сравнение с плавающей запятой:

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

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

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

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

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

Примечания

Инструкции dcmpg и dcmpl отличаются только обработкой сравнения, включающего NaN. NaN неупорядочено, поэтому любое сравнение double терпит неудачу, если один или оба операнда являются NaN. При наличии как dcmpg, так и dcmpl, любое double сравнение может быть скомпилировано для помещения того же значения result на стек операндов, независимо от того, терпит ли неудачу сравнение по значениям, не являющимся NaN, или из-за того, что встретился NaN. Дополнительная информация содержится в §3.5.

dconst_

Операция

Положить double

Формат


dconst_

Формы

dconst_0 = 14 (0xe)

dconst_1 = 15 (0xf)

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

... →

..., <d>

Описание

Положить константу double <d> (0.0 или 1.0) на стек операндов.

ddiv

Операция

Деление

Формат


ddiv

Формы

ddiv = 111 (0x6f)

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

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

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

Описание

Оба значение1 и значение2 должны быть типа double. Значения извлекаются из стека операндов и преобразуются согласно правилам преобразования наборов значений (§2.8.3), что даёт значение1' и значение2'. Результат результат равен значение1' / значение2'. Результат помещается в стек операндов.

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

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

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

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

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

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

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

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

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

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

dload

Операция

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

Формат


dload
index

Формы

dload = 24 (0x18)

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

... →

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

Описание

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)

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

... →

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

Описание

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

Примечания

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

dmul

Операция

Умножение double

Формат


dmul

Формы

dmul = 107 (0x6b)

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

..., value1, value2 →

..., result

Описание

Оба value1 и value2 должны быть типа double. Значения извлекаются из стека операндов и преобразуются в соответствии с набором значений (§2.8.3), в результате чего получаются value1' и value2'. Результат double равен value1' * value2'. Результат result помещается в стек операндов.

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

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

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

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

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

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

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

dneg

Операция

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

Формат


dneg

Формы

dneg = 119 (0x77)

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

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

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

Описание

Значение должно быть типа double. Оно извлекается из стека операндов и преобразуется к набору значений (§2.8.3), что приводит к значению'. double результат - это арифметическое отрицание значения'. Результат помещается в стек операндов.

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

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

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

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

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

drem

Операция

Остаток double

Формат


drem

Формы

drem = 115 (0x73)

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

..., value1, value2 →

..., result

Описание

Оба значения value1 и value2 должны быть типа double. Значения извлекаются из стека операндов и преобразуются с помощью преобразования набора значений (§2.8.3), получая value1' и value2'. Результат result вычисляется и помещается в стек операндов как значение типа double.

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

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

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

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

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

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

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

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

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

Примечания

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

dreturn

Операция

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

Формат


dreturn

Формы

dreturn = 175 (0xaf)

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

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

[пусто]

Описание

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

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

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

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

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

dstore

Операция

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

Формат


dstore
индекс

Формы

dstore = 57 (0x39)

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

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

...

Описание

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

Примечания

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

dstore_<n>

Операция

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

Формат


dstore_<n>

Формы

dstore_0 = 71 (0x47)

dstore_1 = 72 (0x48)

dstore_2 = 73 (0x49)

dstore_3 = 74 (0x4a)

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

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

...

Описание

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

Примечания

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

dsub

Операция

Вычитание double

Формат


dsub

Формы

dsub = 103 (0x67)

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

..., value1, value2 →

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

Описание

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

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

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

dup

Операция

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

Формат


dup

Формы

dup = 89 (0x59)

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

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

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

Описание

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

Инструкция dup не должна использоваться, если значение не является значением вычислительного типа категории 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

Операция

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

Формат


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)

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

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

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

Описание

Значение значение на вершине стека операндов должно быть типа float. Оно извлекается из стека операндов и преобразуется с использованием преобразования набора значений (§2.8.3), в результате получается значение'. Затем значение' преобразуется в double результат. Этот результат помещается в стек операндов.

Примечания

Когда инструкция f2d является FP-строгой (§2.8.2), она выполняет расширяющее преобразование примитивного типа (JLS §5.1.2). Поскольку все значения набора значений float (§2.3.2) точно представимы значениями набора значений double (§2.3.2), такое преобразование является точным.

Если инструкция f2d не является FP-строгой, результат преобразования может быть взят из набора значений с расширенным порядком двойной точности; он не обязательно округляется до ближайшего представимого значения в наборе значений double. Однако, если операнд значение взят из набора значений с расширенным порядком одинарной точности, а целевой результат ограничен набором значений double, может потребоваться округление значение.

f2i

Операция

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

Формат


f2i

Формы

f2i = 139 (0x8b)

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

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

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

Описание

Значение значение на вершине стека операндов должно быть типа float. Оно извлекается из стека операндов и преобразуется с помощью преобразования множества значений (§2.8.3), в результате чего получается значение'. Затем значение' преобразуется в int результат. Этот результат помещается в стек операндов:

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

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

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

Примечания

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

f2l

Операция

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

Формат


f2l

Формы

f2l = 140 (0x8c)

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

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

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

Описание

Значение значение на вершине стека операндов должно быть типа float. Оно извлекается из стека операндов и преобразуется с помощью преобразования набора значений (§2.8.3), в результате чего получается значение'. Затем значение' преобразуется в long результат. Этот результат помещается в стек операндов:

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

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

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

Примечания

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

fadd

Операция

Сложить float

Формат


fadd

Формы

fadd = 98 (0x62)

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

..., value1, value2 →

..., result

Описание

Оба значения value1 и value2 должны быть типа float. Эти значения извлекаются из стека операндов и подвергаются преобразованию типов (§2.8.3), в результате чего получаются value1' и value2'. Результат result вычисляется как value1' + value2'. Результат записывается в стек операндов.

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

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

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

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

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

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

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

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

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

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

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

faload

Операция

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

Формат


faload

Формы

faload = 48 (0x30)

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

..., arrayref, index →

..., value

Описание

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

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

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

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

fastore

Операция

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

Формат


fastore

Формы

fastore = 81 (0x51)

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

..., arrayref, index, value →

...

Описание

Тип arrayref должен быть reference, и он должен ссылаться на массив, чьи компоненты имеют тип float. index должен быть типа int, а value должен быть типа float. arrayref, index и value извлекаются из стека операндов. Значение value подвергается преобразованию (§2.8.3), в результате получаем 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. Значения извлекаются из стека операндов и подвергаются преобразованию множества значений (§2.8.3), что приводит к value1' и value2'. Выполняется сравнение с плавающей точкой:

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

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

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

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

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

Примечания

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

fconst_

Операция

Положить float

Формат


fconst_

Формы

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)

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

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

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

Описание

Оба значение1 и значение2 должны быть типа float. Значения извлекаются из стека операндов и подвергаются преобразованию набора значений (§2.8.3), в результате чего получаются значение1' и значение2'. Полученный float результат равен значение1' / значение2'. Результат записывается в стек операндов.

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

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

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

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

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

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

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

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

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

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

fload

Операция

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

Формат


fload
index

Формы

fload = 23 (0x17)

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

... →

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

Описание

index — это беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей фрейма (§2.6). Локальная переменная по индексу index должна содержать float. Значение локальной переменной по индексу 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)

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

... →

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

Описание

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

Примечания

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

fmul

Операция

Умножение float

Формат


fmul

Формы

fmul = 106 (0x6a)

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

..., value1, value2 →

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

Описание

Оба value1 и value2 должны быть типа float. Значения извлекаются из стека операндов и преобразуются (§2.8.3), что приводит к значениям value1' и value2'. Полученный float результат равен value1' * value2'. Результат помещается в стек операндов.

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

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

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

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

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

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

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

fneg

Операция

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

Формат


fneg

Формы

fneg = 118 (0x76)

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

..., value →

..., result

Описание

Значение value должно быть типа float. Оно извлекается из стека операндов и претерпевает преобразование набора значений (§2.8.3), что приводит к value'. Результат result является арифметическим отрицанием value'. Этот result помещается в стек операндов.

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

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

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

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

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

frem

Операция

Остаток float

Формат


frem

Формы

frem = 114 (0x72)

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

..., value1, value2 →

..., result

Описание

Оба value1 и value2 должны быть типа float. Значения извлекаются из стека операндов и преобразуются с помощью преобразования набора значений (§2.8.3), в результате чего получаются value1' и value2'. result вычисляется и помещается в стек операндов как float.

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

Результат инструкции frem регулируется следующими правилами:

  • Если 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.

freturn

Операция

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

Формат


freturn

Формы

freturn = 174 (0xae)

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

..., value →

[пусто]

Описание

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

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

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

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

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

fstore

Операция

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

Формат


fstore
index

Формы

fstore = 56 (0x38)

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

..., value →

...

Описание

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

Примечания

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

fstore_<n>

Операция

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

Формат


fstore_<n>

Формы

fstore_0 = 67 (0x43)

fstore_1 = 68 (0x44)

fstore_2 = 69 (0x45)

fstore_3 = 70 (0x46)

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

..., value →

...

Описание

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

Примечания

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

fsub

Операция

Вычитание float

Формат


fsub

Формы

fsub = 102 (0x66)

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

..., value1, value2 →

..., result

Описание

И value1, и value2 должны быть типа float. Значения извлекаются из стека операндов и подвергаются преобразованию типа значений (§2.8.3), в результате чего получаются value1' и value2'. Результирующее значение result равно value1' - value2'. Результат помещается в стек операндов.

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

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

getfield

Операция

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

Формат


getfield
indexbyte1
indexbyte2

Формы

getfield = 180 (0xb4)

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

..., objectref →

..., value

Описание

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

Тип objectref не должен быть типом массива. Если поле является protected (§4.6), и оно является членом суперкласса текущего класса, и поле не объявлено в том же пакете времени выполнения (§5.3), что и текущий класс, то класс objectref должен быть либо текущим классом, либо подклассом текущего класса.

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

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

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

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

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

Примечания

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

getstatic

Операция

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

Формат


getstatic
indexbyte1
indexbyte2

Формы

getstatic = 178 (0xb2)

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

..., →

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

Описание

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

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

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

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

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

В противном случае, если разрешенное поле не является полем класса (класса) или полем интерфейса, 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.

i2b

Операция

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

Формат


i2b

Формы

i2b = 145 (0x91)

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

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

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

Описание

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

Примечания

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

i2c

Операция

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

Формат


i2c

Формы

i2c = 146 (0x92)

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

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

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

Описание

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

Примечания

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

i2d

Операция

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

Формат


i2d

Формы

i2d = 135 (0x87)

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

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

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

Описание

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

Примечания

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

i2f

Операция

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

Формат


i2f

Формы

i2f = 134 (0x86)

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

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

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

Описание

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

Примечания

Инструкция 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)

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

..., value1, value2 →

..., result

Описание

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

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

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

iaload

Операция

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

Формат


iaload

Формы

iaload = 46 (0x2e)

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

..., arrayref, index →

..., value

Описание

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

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

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

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

iand

Операция

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

Формат


iand

Формы

iand = 126 (0x7e)

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

..., value1, value2 →

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

Описание

Оба value1 и value2 должны быть типа int. Они извлекаются из стека операндов. int результат вычисляется путём поразрядного И (конъюнкции) value1 и value2. результат помещается в стек операндов.

iastore

Операция

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

Формат


iastore

Формы

iastore = 79 (0x4f)

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

..., arrayref, индекс, значение →

...

Описание

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

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

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

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

iconst_

Операция

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

Формат


iconst_

Формы

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>

Описание

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

Примечания

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

idiv

Операция

Деление

Формат


idiv

Формы

idiv = 108 (0x6c)

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

..., value1, value2 →

..., result

Описание

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

Операция целочисленного деления округляется к нулю; то есть, частное, полученное при делении n/d, — это значение q с наибольшим модулем, удовлетворяющее условию |d · q| ≤ |n|. Кроме того, q положительно, когда |n| ≥ |d| и n и d имеют одинаковый знак, но q отрицательно, когда |n| ≥ |d| и n и d имеют разные знаки.

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

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

Если значение делителя в операции целочисленного деления равно 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. Затем выполнение продолжается в этом смещении от адреса инструкции opcode данного if_acmp<cond>. Целевой адрес должен быть адресом инструкции opcode в методе, содержащем данную инструкцию 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
index

Формы

iload = 21 (0x15)

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

... →

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

Описание

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

Примечания

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

iload_

Операция

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

Формат


iload_

Формы

iload_0 = 26 (0x1a)

iload_1 = 27 (0x1b)

iload_2 = 28 (0x1c)

iload_3 = 29 (0x1d)

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

... →

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

Описание

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

Примечания

Каждая из инструкций iload_ эквивалентна инструкции 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 Результат — арифметическое отрицание значения, -значение. Результат помещается в стек операндов.

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

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

instanceof

Операция

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

Формат


instanceof
indexbyte1
indexbyte2

Формы

instanceof = 193 (0xc1)

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

..., objectref →

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

Описание

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

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

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

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

  • Если S — обычный (не массива) класс, то:

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

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

  • Если S — тип интерфейса, то:

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

    • Если T — тип интерфейса, то T должен быть тем же интерфейсом, что и S, или над-интерфейсом S.

  • Если 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 ...]] →

...

Описание

Каждое конкретное лексическое вхождение инструкции invokedynamic называется динамической точкой вызова.

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

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

Далее, в рамках продолжающегося разрешения спецификатора точки вызова, метод загрузки вызывается так, как если бы он выполнялся инструкцией invokevirtual (§invokevirtual), содержащей индекс пула постоянных времени выполнения на символическую ссылку на метод (§5.1) со следующими свойствами:

  • Имя метода равно invoke;

  • Описание метода имеет возвращаемый тип java.lang.invoke.CallSite;

  • Описание метода имеет типы параметров, полученные из элементов, помещённых в стек операндов, следующим образом.

    Первые четыре типа параметров в описании — java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandles.Lookup, String и java.lang.invoke.MethodType в указанном порядке.

    Если у спецификатора точки вызова есть статические аргументы, то для каждого аргумента добавляется тип параметра к типам параметров описания метода в том порядке, в котором аргументы были помещены в стек операндов. Эти типы параметров могут быть Class, java.lang.invoke.MethodHandle, java.lang.invoke.MethodType, String, int, long, float или double.

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

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

  • reference на объект java.lang.invoke.MethodHandle для метода загрузки;

  • reference на объект java.lang.invoke.MethodHandles.Lookup для класса, в котором происходит данная динамическая точка вызова;

  • reference на String для имени метода в спецификаторе точки вызова;

  • reference на объект java.lang.invoke.MethodType, полученный для описания метода в спецификаторе точки вызова;

  • reference для классов, типов методов, хэндлов методов и строковых литералов, обозначенных как статические аргументы в спецификаторе точки вызова, а также числовых значений (§2.3.1, §2.3.2), обозначенных как статические аргументы в спецификаторе точки вызова, в порядке их появления в спецификаторе точки вызова. (То есть, для примитивных значений упаковка не происходит.)

До тех пор, пока метод загрузки может быть правильно вызван методом invoke, его описание произвольно. Например, первый тип параметра мог бы быть Object вместо java.lang.invoke.MethodHandles.Lookup, а тип возвращаемого значения — также Object вместо java.lang.invoke.CallSite.

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

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

Результат, возвращаемый методом bootstrap, должен быть ссылкой на объект, класс которого является java.lang.invoke.CallSite или подклассом java.lang.invoke.CallSite. Этот объект известен как объект сайта вызова. reference извлекается из стека операндов, как если бы выполнялась инструкция invokevirtual.

Если несколько потоков одновременно выполняют метод bootstrap для одного и того же динамического сайта вызова, виртуальная машина Java должна выбрать один объект сайта вызова и установить его видимым для всех потоков. Любые другие методы bootstrap, выполняемые для динамического сайта вызова, могут завершиться, но их результаты игнорируются, и выполнение динамического сайта вызова в потоках продолжается с выбранным объектом сайта вызова.

Объект сайта вызова имеет описатель типа (экземпляр java.lang.invoke.MethodType), который должен быть семантически равен объекту java.lang.invoke.MethodType, полученному для описателя метода в спецификаторе сайта вызова.

Результат успешного разрешения спецификатора сайта вызова — это объект сайта вызова, который постоянно связан с динамическим сайтом вызова.

Метод, представленный целевым объектом связанного сайта вызова, вызывается. Вызов происходит как если бы выполнялась инструкция invokevirtual (§invokevirtual), указывающая индекс пула констант времени выполнения на символическую ссылку на метод (§5.1) со следующими свойствами:

  • Имя метода — invokeExact;

  • Описатель метода — описатель метода в спецификаторе сайта вызова; и

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

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

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

Если при разрешении символической ссылки на спецификатор сайта вызова возникает исключение E, инструкция invokedynamic генерирует исключение BootstrapMethodError, которое оборачивает E.

В противном случае, во время дальнейшего разрешения спецификатора сайта вызова, если вызов метода bootstrap завершается прерывисто (§2.6.5) из-за генерации исключения E, инструкция invokedynamic генерирует исключение BootstrapMethodError, которое оборачивает E. (Это может произойти, если у метода bootstrap неправильная арность, тип параметра или тип возвращаемого значения, что приводит к java.lang.invoke.MethodHandle . invoke генерировать java.lang.invoke.WrongMethodTypeException.)

В противном случае, во время дальнейшего разрешения спецификатора сайта вызова, если результат вызова метода bootstrap не является ссылкой на экземпляр java.lang.invoke.CallSite, инструкция invokedynamic генерирует исключение BootstrapMethodError.

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

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

Если данный динамический сайт вызова завершил разрешение своего спецификатора сайта вызова, это означает, что ссылка на экземпляр java.lang.invoke.CallSite привязана к этому динамическому сайту вызова. Поэтому элемент стека операндов, представляющий ссылку на цель объекта сайта вызова, никогда не null. Аналогично, это означает, что описатель метода в спецификаторе сайта вызова семантически равен описателю типа обработчика метода для вызова, как если бы выполнялась инструкция invokevirtual.

Эти инварианты означают, что инструкция invokedynamic, связанная с объектом сайта вызова, никогда не генерирует исключение 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) или методом инициализации класса или интерфейса (§2.9).

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

Пусть C — класс objectref. Фактический вызываемый метод выбирается следующей процедурой поиска:

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

  • В противном случае, если у C есть суперкласс, эта процедура поиска выполняется рекурсивно с использованием непосредственного суперкласса C; метод, который будет вызван, — результат рекурсивного вызова этой процедуры поиска.

  • В противном случае, генерируется AbstractMethodError.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Примечания

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

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

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

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). Наконец, если разрешённый метод является protected (§4.6), является членом суперкласса текущего класса и метод не объявлен в том же пакете времени выполнения (§5.3), что и текущий класс, то класс objectref должен быть либо текущим классом, либо подклассом текущего класса.

Далее, разрешённый метод выбирается для вызова, если не выполняются все следующие условия:

  • Флаг ACC_SUPER (Таблица 4.1) установлен для текущего класса.

  • Класс разрешённого метода является суперклассом текущего класса.

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

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

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

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

  • В противном случае, возникает AbstractMethodError.

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

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

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

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

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

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

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

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

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

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

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

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

В противном случае, если ни один метод, соответствующий разрешённому имени и описанию, не выбран, invokespecial генерирует AbstractMethodError.

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

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

Примечания

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

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

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

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). Разрешённый метод не должен быть методом инициализации экземпляра (§2.9) или методом инициализации класса или интерфейса (§2.9). Он должен быть static, и поэтому не может быть abstract.

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

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

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

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

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

  • Если метод 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) или методом инициализации класса или интерфейса (§2.9). Наконец, если разрешенный метод является protected (§4.6), и он является членом суперкласса текущего класса, и метод не объявлен в той же среде выполнения (§5.3) , что и текущий класс, то класс objectref должен быть либо текущим классом, либо подклассом текущего класса.

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

Пусть C — класс objectref. Фактический вызываемый метод выбирается с помощью следующей процедуры поиска:

  • Если C содержит объявление экземпляра метода m, который переопределяет (§5.4.5) разрешенный метод, то m является вызываемым методом, и процедура поиска завершается.

  • В противном случае, если C имеет суперкласс, эта же процедура поиска выполняется рекурсивно с использованием непосредственного суперкласса C; вызываемым методом является результат рекурсивного вызова этой процедуры поиска.

  • В противном случае генерируется AbstractMethodError.

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

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

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

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

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

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

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

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

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

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

  • Если метод с указанным именем является invoke, и экземпляр java.lang.invoke.MethodType не семантически равен дескриптору типа получателя дескриптора метода objectref, то виртуальная машина Java пытается скорректировать дескриптор типа получателя дескриптора метода, как если бы был вызван java.lang.invoke.MethodHandle.asType, чтобы получить точно вызываемый дескриптор метода 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 вызывает его способом, зависящим от реализации.

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

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

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

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

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

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

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

  • Если метод, соответствующий разрешённому имени и описателю, не выбран, invokevirtual генерирует исключение AbstractMethodError.

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

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

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

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

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

Примечания

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

ior

Операция

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

Формат


ior

Формы

ior = 128 (0x80)

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

..., value1, value2 →

..., result

Описание

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

END_OF_DOCUMENT_MARKER

irem

Операция

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

Формат


irem

Формы

irem = 112 (0x70)

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

..., value1, value2 →

..., result

Описание

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

Результат инструкции irem таков, что int равно (a/b)*b + (a%b). Это равенство выполняется даже в том частном случае, когда делимое является отрицательным a максимального возможного значения для своего типа, а делитель равен -1 (остаток равен 0). Из этого правила следует, что результат операции остатка может быть отрицательным только если делимое отрицательное и может быть положительным только если делимое положительное. Кроме того, величина результата всегда меньше величины делителя.

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

Если значение делителя для операции остатка от деления int равно 0, irem вызывает исключение int.

ireturn

Операция

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

Формат


ireturn

Формы

ireturn = 172 (0xac)

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

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

[пустой]

Описание

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

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

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

Если реализация 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 — значение младших 5 битов value2. result помещается в стек операндов.

Примечания

Результирующее значение равно ⌊ value1 / 2s ⌋, где s — value2 & 0x1f. Для неотрицательного value1 это эквивалентно усечению int деления на 2 в степени s. Расстояние сдвига, фактически используемое, всегда находится в диапазоне от 0 до 31 включительно, как если бы value2 было подвергнуто побитовому логическому И с маской 0x1f.

istore

Операция

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

Формат


istore
индекс

Формы

istore = 54 (0x36)

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

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

...

Описание

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

Примечания

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

istore_<n>

Операция

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

Формат


istore_<n>

Формы

istore_0 = 59 (0x3b)

istore_1 = 60 (0x3c)

istore_2 = 61 (0x3d)

istore_3 = 62 (0x3e)

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

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

...

Описание

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

Примечания

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

isub

Операция

Вычитание int

Формат


isub

Формы

isub = 100 (0x64)

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

..., value1, value2 →

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

Описание

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

Для вычитания int, a-b даёт тот же результат, что и a+(-b). Для int значений, вычитание из нуля эквивалентно взятию отрицания.

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

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

iushr

Операция

Логическое правое сдвиг int

Формат


iushr

Формы

iushr = 124 (0x7c)

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

..., value1, value2 →

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

Описание

Оба value1 и value2 должны быть типа int. Значения извлекаются из стека операндов. Результат результат рассчитывается путем сдвига value1 вправо на s позиций бита с расширением нуля, где s — значение 5 младших битов value2. Результат результат помещается в стек операндов.

Примечания

Если value1 положительно, а s — value2 & 0x1f, результат совпадает с результатом value1 >> s; если value1 отрицательно, результат равен значению выражения (value1 >> s) + (2 << ~s). Сложение члена (2 << ~s) компенсирует распространяемый знаковый бит. Расстояние сдвига, фактически используемое, всегда находится в диапазоне от 0 до 31 включительно.

ixor

Операция

Булево XOR int

Формат


ixor

Формы

ixor = 130 (0x82)

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

..., value1, value2 →

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

Описание

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

jsr

Операция

Переход к подпрограмме

Формат


jsr
branchbyte1
branchbyte2

Формы

jsr = 168 (0xa8)

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

... →

..., адрес

Описание

Адрес инструкции, следующей сразу за этой инструкцией 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)

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

... →

..., адрес

Описание

Адрес (opcode) инструкции, следующей непосредственно за инструкцией jsr_w, помещается в стек операндов как значение типа returnAddress. Беззнаковые branchbyte1, branchbyte2, branchbyte3 и branchbyte4 используются для построения 32-битного смещения со знаком, где смещение равно (branchbyte1 << 24) | (branchbyte2 << 16) | (branchbyte3 << 8) | branchbyte4. Выполнение продолжается по смещению от адреса инструкции jsr_w. Адрес назначения должен соответствовать адресу opcode инструкции внутри метода, содержащего инструкцию 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.

l2d

Операция

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

Формат


l2d

Формы

l2d = 138 (0x8a)

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

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

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

Описание

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

Примечания

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

l2f

Операция

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

Формат


l2f

Формы

l2f = 137 (0x89)

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

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

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

Описание

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

Примечания

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

l2i

Операция

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

Формат


l2i

Формы

l2i = 136 (0x88)

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

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

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

Описание

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

Примечания

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

ladd

Операция

Сложить long

Формат


ladd

Формы

ladd = 97 (0x61)

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

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

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

Описание

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

Результат является 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_

Операция

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

Формат


lconst_

Формы

lconst_0 = 9 (0x9)

lconst_1 = 10 (0xa)

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

... →

..., <l>

Описание

Положить константу long <l> (0 или 1) на стек операндов.

ldc

Операция

Положить элемент из пула констант времени выполнения

Формат


ldc
индекс

Формы

ldc = 18 (0x12)

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

... →

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

Описание

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

Если элемент пула констант времени выполнения — это константа времени выполнения типа int или float, то числовое значение этой константы помещается в стек операндов как int или float соответственно.

В противном случае, если элемент пула констант времени выполнения — это символическая ссылка на экземпляр класса String, представляющего строковую литерал (§5.1), то ссылка на этот экземпляр, значение, помещается в стек операндов.

В противном случае, если элемент пула констант времени выполнения — это символическая ссылка на класс (§5.1), то указанный класс разрешается (§5.4.3.1) и ссылка на объект, представляющий этот класс, значение, помещается в стек операндов.

В противном случае, элемент пула констант времени выполнения должен быть символической ссылкой на тип метода или обработчик метода (§5.1). Тип метода или обработчик метода разрешаются (§5.4.3.5) и ссылка на полученный экземпляр java.lang.invoke.MethodType или java.lang.invoke.MethodHandle, значение, помещается в стек операндов.

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

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

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

Примечания

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

ldc_w

Операция

Помещает элемент из пула констант во время выполнения (индекс с расширенным значением)

Формат


ldc_w
indexbyte1
indexbyte2

Формы

ldc_w = 19 (0x13)

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

... →

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

Описание

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

Если элемент пула констант — константа типа int или float, числовое значение этой константы помещается в стек операндов как int или float, соответственно.

В противном случае, если элемент пула констант — ссылка на экземпляр класса String, представляющего строковый литерал (§5.1), то ссылка на этот экземпляр, значение, помещается в стек операндов.

В противном случае, если элемент пула констант — символическая ссылка на класс (§4.4.1). Наименованный класс разрешается (§5.4.3.1) и ссылка на объект, представляющий этот класс, значение, помещается в стек операндов.

В противном случае, элемент пула констант должен быть символической ссылкой на тип метода или дескриптор метода (§5.1). Тип метода или дескриптор метода разрешается (§5.4.3.5) и ссылка на полученный экземпляр java.lang.invoke.MethodType или java.lang.invoke.MethodHandle, значение, помещается в стек операндов.

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

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

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

Примечания

Инструкция ldc_w идентична инструкции ldc (§ldc), за исключением более широкого индекса пула констант во время выполнения.

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

ldc2_w

Операция

Поместить long или double из пула постоянных значений во время выполнения (индекс с расширенным диапазоном)

Формат


ldc2_w
indexbyte1
indexbyte2

Формы

ldc2_w = 20 (0x14)

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

... →

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

Описание

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

Примечания

Существует только форма инструкции ldc2_w с расширенным индексом; нет инструкции ldc2, которая помещает long или double с однобайтовым индексом.

Инструкция ldc2_w может использоваться только для помещения значения типа double из набора значений типа double (§2.3.2), так как константа типа double в пуле постоянных значений (§4.4.5) должна быть из набора значений типа double.

ldiv

Операция

Деление

Формат


ldiv

Формы

ldiv = 109 (0x6d)

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

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

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

Описание

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

Деление округляется до нуля; то есть, частное, полученное для long значений в n / d — это long значение 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)

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

... →

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

Описание

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

Примечания

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

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)

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

..., value1, value2 →

..., result

Описание

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

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

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

lneg

Операция

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

Формат


lneg

Формы

lneg = 117 (0x75)

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

..., value →

..., result

Описание

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

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

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

lookupswitch

Операция

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

Формат


lookupswitch
<0-3 байтовый заполнитель>
defaultbyte1
defaultbyte2
defaultbyte3
defaultbyte4
npairs1
npairs2
npairs3
npairs4
пары match-offset...

Формы

lookupswitch = 171 (0xab)

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

..., ключ →

...

Описание

Инструкция lookupswitch имеет переменную длину. Непосредственно после кода операции lookupswitch от нуля до трёх байтов должны быть заполнителем, таким образом, чтобы defaultbyte1 начинался по адресу, кратно четырём байтам от начала текущего метода (кода первой инструкции). Непосредственно после заполнителя следуют ряд знаковых 32-битных значений: default, npairs, а затем npairs пар знаковых 32-битных значений. npairs должно быть больше или равно 0. Каждая из пар npairs состоит из int match и знакового 32-битного offset. Каждое из этих знаковых 32-битных значений создаётся из четырёх беззнаковых байтов как (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4.

Таблица пар match-offset инструкции lookupswitch должна быть отсортирована по возрастанию match.

Ключ должен быть типа int и извлекается из стека операндов. Ключ сравнивается со значениями match. Если он равен одному из них, то адрес назначения вычисляется путем добавления соответствующего offset к адресу кода операции этой инструкции lookupswitch. Если ключ не совпадает ни с одним из значений match, то адрес назначения вычисляется путём добавления default к адресу кода операции этой инструкции lookupswitch. Выполнение затем продолжается по адресу назначения.

Адрес назначения, который может быть вычислен из offset каждой пары match-offset, а также вычисленный из default, должен быть адресом кода операции инструкции внутри метода, который содержит эту инструкцию lookupswitch.

Примечания

Требуемое выравнивание 4-байтовых операндов инструкции lookupswitch гарантирует 4-байтовое выравнивание этих операндов тогда и только тогда, когда метод, который содержит lookupswitch, расположен на 4-байтовой границе.

Пары match-offset отсортированы для поддержки процедур поиска, которые быстрее, чем линейный поиск.

lor

Операция

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

Формат


lor

Формы

lor = 129 (0x81)

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

..., value1, value2 →

..., result

Описание

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

lrem

Операция

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

Формат


lrem

Формы

lrem = 113 (0x71)

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

..., value1, value2 →

..., result

Описание

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

Результат инструкции lrem таков, что (a/b)*b + (a%b) равно a. Это тождество выполняется и в том частном случае, когда делимое является отрицательным long наибольшего возможного значения для своего типа, а делитель равен -1 (остаток равен 0). Из этого правила следует, что результат операции остатка может быть отрицательным только если делимое отрицательное, и может быть положительным только если делимое положительное; кроме того, величина результата всегда меньше величины делителя.

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

Если значение делителя для long операции вычисления остатка равно 0, инструкция lrem генерирует исключение ArithmeticException.

lreturn

Операция

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

Формат


lreturn

Формы

lreturn = 173 (0xad)

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

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

[пустой]

Описание

Текущий метод должен иметь тип возвращаемого значения long. Значение значение должно быть типа long. Если текущий метод является методом synchronized, монитор, вошедший или повторно вошедший при вызове метода, обновляется и, возможно, завершается так, как если бы выполнялась инструкция monitorexit (§monitorexit) в текущем потоке. Если исключение не выбрасывается, значение извлекается из стека операндов текущей рамки (§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. Значения извлекаются из стека операндов. Вычисляется значение 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. Значения извлекаются из стека операндов. Вычисляется значение result путём сдвига value1 вправо на s бит с расширением знака, где s — значение 6 младших битов value2. Значение result помещается в стек операндов.

Примечания

Полученное значение равно ⌊ value1 / 2s ⌋, где s равно value2 & 0x3f. Для неотрицательных value1 это эквивалентно усечению результата деления на 2 в степени s. Расстояние сдвига всегда находится в диапазоне от 0 до 63 включительно, как если бы value2 было подвергнуто побитовому логическому И с маской 0x3f.

lstore

Операция

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

Формат


lstore
индекс

Формы

lstore = 55 (0x37)

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

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

...

Описание

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

Примечания

Инструкция 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)

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

..., value1, value2 →

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

Описание

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

Для long вычитания, a-b производит тот же результат, что и a+(-b). Для long значений, вычитание из нуля равно отрицанию.

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

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

lushr

Операция

Логический сдвиг вправо long

Формат


lushr

Формы

lushr = 125 (0x7d)

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

..., value1, value2 →

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

Описание

value1 должен быть типа long, а value2 — типа int. Значения извлекаются из стека операндов. long результат вычисляется путём логического сдвига value1 вправо (с расширением нулями) на величину, указанную 6 младшими битами value2. Результат помещается на стек операндов.

Примечания

Если value1 положительное, а s равно value2 & 0x3f, результат совпадает с результатом value1 >> s; если value1 отрицательное, результат равен значению выражения (value1 >> s) + (2L << ~s). Добавление члена (2L << ~s) компенсирует распространяемый знаковый бит. Расстояние сдвига, фактически используемое, всегда находится в диапазоне от 0 до 63 включительно.

lxor

Операция

Булево XOR long

Формат


lxor

Формы

lxor = 131 (0x83)

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

..., value1, value2 →

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

Описание

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

monitorenter

Операция

Вход в монитор для объекта

Формат


monitorenter

Формы

monitorenter = 194 (0xc2)

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

..., objectref →

...

Описание

objectref должен быть типа reference.

Каждый объект связан с монитором. Монитор заблокирован, если и только если у него есть владелец. Поток, который выполняет monitorenter, пытается получить владение монитором, связанным с objectref, следующим образом:

  • Если счётчик входов монитора, связанного с objectref, равен нулю, поток входит в монитор и устанавливает счётчик входов в единицу. Затем этот поток становится владельцем монитора.

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

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

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

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

Примечания

Инструкция monitorenter может быть использована с одной или несколькими инструкциями monitorexit (§monitorexit) для реализации оператора блокировки в языке программирования Java (§3.14). Инструкции monitorenter и monitorexit не используются в реализации методов synchronized, хотя они могут быть использованы для предоставления эквивалентной семантики блокировки. Вход в монитор при вызове метода synchronized и выход из монитора при его возвращении неявно обрабатываются инструкцией вызова и возврата метода виртуальной машины Java, как если бы использовались инструкции monitorenter и monitorexit.

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

Конструкции синхронизации языка программирования Java требуют поддержки операций над мониторами помимо входа и выхода. К ним относятся ожидание монитора (Object.wait) и уведомление других потоков, ожидающих монитора (Object.notifyAll и Object.notify). Эти операции поддерживаются в стандартном пакете java.lang, поставляемом с виртуальной машиной Java. Явный механизм поддержки этих операций не присутствует в наборе инструкций виртуальной машины Java.

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).

многомерный массив

Операция

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

Формат


многомерный массив
индексбайт1
индексбайт2
размерности

Формы

многомерный массив = 197 (0xc5)

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

..., счёт1, [счёт2, ...] →

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

Описание

Операнд размерности — это беззнаковый байт, который должен быть больше или равен 1. Он представляет количество измерений создаваемого массива. В стеке операндов должно быть размерности значений. Каждое из этих значений представляет количество компонентов в измерении создаваемого массива, должно быть типа int и должно быть неотрицательным. счёт1 — это желаемая длина в первом измерении, счёт2 — во втором и так далее.

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

Новый многомерный массив указанного типа выделяется из кучи сборки мусора. Если какое-либо значение счёт равно нулю, последующие измерения не выделяются. Компоненты массива в первом измерении инициализируются подмассивами типа второго измерения и так далее. Компоненты последнего выделенного измерения массива инициализируются стандартным начальным значением (§2.3, §2.4) для типа элемента типа массива. reference ссылка ссылка_на_массив на новый массив помещается в стек операндов.

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

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

В противном случае, если у текущего класса нет разрешения на доступ к типу элемента разрешённого типа массива, многомерный массив вызывает IllegalAccessError.

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

В противном случае, если любое из значений размерности в стеке операндов меньше нуля, инструкция многомерный массив вызывает 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.

В противном случае, если символическая ссылка на тип класса, массива или интерфейса разрешается на интерфейс или является типом abstract класса, new выбросит исключение InstantiationError.

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

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

Примечания

Инструкция new не полностью создает новый экземпляр; создание экземпляра не завершается до тех пор, пока метод инициализации экземпляра (§2.9) не будет вызван на неинициализированном экземпляре.

newarray

Операция

Создать новый массив

Формат


newarray
atype

Формы

newarray = 188 (0xbc)

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

..., count →

..., arrayref

Описание

count должен быть типа int. Он извлекается из стека операндов. count представляет количество элементов создаваемого массива.

atype — код, указывающий тип создаваемого массива. Он должен принимать одно из следующих значений:

Таблица 6.1. Коды типов массивов

Тип массива 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), которое предоставляет имя и дескриптор поля, а также символическую ссылку на класс, в котором находится поле. Класс objectref не должен быть массивом. Если поле является protected (§4.6), и оно является членом суперкласса текущего класса, и поле не объявлено в той же пакетной среде выполнения (§5.3), что и текущий класс, то класс objectref должен быть либо текущим классом, либо подклассом текущего класса.

Ссылаемое поле разрешается (§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, оно должно быть объявлено в текущем классе, и инструкция должна выполняться в методе инициализации экземпляра (<init>) текущего класса (§2.9).

value и objectref извлекаются из стека операндов. objectref должен быть типа reference. value претерпевает преобразование в наборе значений (§2.8.3), что приводит к value', и ссылаемое поле в objectref устанавливается в value'.

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

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

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

В противном случае, если поле является final, оно должно быть объявлено в текущем классе, а инструкция должна выполняться в методе инициализации экземпляра (<init>) текущего класса. В противном случае возбуждается исключение 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, оно должно быть объявлено в текущем классе, а инструкция должна выполняться в методе <clinit> текущего класса (§2.9).

Значение значение извлекается из стека операндов и подвергается преобразованию типа значения (§2.8.3), результатом чего является значение'. Поле класса устанавливается в значение'.

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

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

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

В противном случае, если поле является final, оно должно быть объявлено в текущем классе, а инструкция должна выполняться в методе <clinit> текущего класса. В противном случае генерируется исключение IllegalAccessError.

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

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

Примечания

Инструкцию putstatic можно использовать только для задания значения поля интерфейса во время инициализации этого поля. Полям интерфейса можно присвоить значение только один раз, при выполнении выражения инициализации переменной интерфейса во время инициализации интерфейса (§5.5, JLS §9.3.1).

ret

Операция

Возврат из подпрограммы

Формат


ret
index

Формы

ret = 169 (0xa9)

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

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

Описание

index — это беззнаковый байт от 0 до 255 включительно. Локальная переменная в текущей области (§2.6) с индексом index должна содержать значение типа returnAddress. Содержимое локальной переменной записывается в регистр pc виртуальной машины Java, и выполнение продолжается оттуда.

Примечания

Обратите внимание, что инструкция jsr (§jsr) помещает адрес на стек операндов, а ret извлекает его из локальной переменной. Эта асимметрия преднамеренная.

В реализации компилятора для языка программирования Java в Oracle до 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 байт заполнения>
defaultbyte1
defaultbyte2
defaultbyte3
defaultbyte4
lowbyte1
lowbyte2
lowbyte3
lowbyte4
highbyte1
highbyte2
highbyte3
highbyte4
смещения переходов...

Формы

tableswitch = 170 (0xaa)

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

..., индекс →

...

Описание

tableswitch — инструкция переменной длины. Сразу после кода операции tableswitch от 0 до 3 байтов должны использоваться в качестве заполнения, таким образом, чтобы defaultbyte1 начинался по адресу, кратно четырём байтам от начала текущего метода (кода операции его первой инструкции). Сразу после заполнения идут байты, представляющие собой три знаковых 32-битных значения: default, low и high. Сразу за ними следуют байты, представляющие собой серию high - low + 1 знаковых 32-битных смещений. Значение low должно быть меньше или равно high. high - low + 1 знаковых 32-битных смещений рассматриваются как таблица переходов с индексацией с 0. Каждое из этих знаковых 32-битных значений строится как (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4.

Значение индекс должно иметь тип int и извлекается из стека операндов. Если индекс меньше low или индекс больше high, то целевой адрес вычисляется путём добавления default к адресу кода операции этой инструкции tableswitch. В противном случае извлекается смещение в позиции индекс - low таблицы переходов. Целевой адрес вычисляется путём добавления этого смещения к адресу кода операции этой инструкции tableswitch. Выполнение затем продолжается по целевому адресу.

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

Примечания

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

широкий

Операция

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

Формат 1


широкий
<opcode>
indexbyte1
indexbyte2

где <opcode> — один из iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore или ret

Формат 2


широкий
iinc
indexbyte1
indexbyte2
constbyte1
constbyte2

Формы

широкий = 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