Spec-Zone.ru › Java Virtual Machine Specification 24

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

Оглавление

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

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

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

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

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

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

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

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

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

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

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

END_OF_DOCUMENT_MARKER

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

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

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

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

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

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

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

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

мнемоника

Операция

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

Формат


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

Формы

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

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

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

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

Описание

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

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

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

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

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

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

Примечания

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

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

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

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

lconst_0 = 9 (0x9)

lconst_1 = 10 (0xa)

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

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

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

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

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

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

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

aaload

Операция

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

Формат


aaload

Формы

aaload = 50 (0x32)

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

..., arrayref, index →

..., value

Описание

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

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

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

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

aastore

Операция

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

Формат


aastore

Формы

aastore = 83 (0x53)

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

..., arrayref, index, value →

...

Описание

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

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

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

Проверка, является ли value значением типа компонента массива, осуществляется в соответствии с правилами, указанными в §checkcast.

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

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

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

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

aconst_null

Операция

Поместить null

Формат


aconst_null

Формы

aconst_null = 1 (0x1)

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

... →

..., null

Описание

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

Примечания

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

aload

Операция

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

Формат


aload
index

Формы

aload = 25 (0x19)

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

... →

..., objectref

Описание

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

Примечания

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

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

aload_<n>

Операция

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

Формат


aload_<n>

Формы

aload_0 = 42 (0x2a)

aload_1 = 43 (0x2b)

aload_2 = 44 (0x2c)

aload_3 = 45 (0x2d)

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

... →

..., objectref

Описание

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

Примечания

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

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

anewarray

Операция

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

Формат


anewarray
indexbyte1
indexbyte2

Формы

anewarray = 189 (0xbd)

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

..., count →

..., arrayref

Описание

Значение count должно быть типа int. Оно извлекается со стека операндов. count представляет количество элементов создаваемого массива. Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле констант времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула констант времени выполнения по этому индексу должен быть символической ссылкой на тип класса, массива или интерфейса. Имя типа класса, массива или интерфейса разрешается (§5.4.3.1). Выделяется новый массив с элементами указанного типа и длиной count в куче с автоматическим сбором мусора, и ссылка arrayref на этот новый объект массива помещается на стек операндов. Все элементы нового массива инициализируются значением 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 не соблюдает правила структурной блокировки, описанные в §2.11.10, то если текущий метод является synchronized методом, а текущий поток не является владельцем монитора, вошедшего или повторно вошедшего при вызове метода, areturn выбрасывает исключение IllegalMonitorStateException. Это может произойти, например, если synchronized метод содержит инструкцию monitorexit, но не инструкцию monitorenter на объекте, на котором метод синхронизирован.

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

Операция

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

Формат


astore_<n>

Формы

astore_0 = 75 (0x4b)

astore_1 = 76 (0x4c)

astore_2 = 77 (0x4d)

astore_3 = 78 (0x4e)

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

..., objectref →

...

Описание

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

Примечания

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

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

Каждая инструкция astore_<n> эквивалентна astore с индексом <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 извлекаются из стека операндов. Значение byte value в компоненте массива по index извлекается, расширяется со знаком до int value, и помещается в верхнюю часть стека операндов.

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

Если arrayref равен null, baload выбрасывает NullPointerException.

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

Примечания

Инструкция baload используется для загрузки значений из массивов как byte, так и boolean. В реализации Java Virtual Machine 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 извлекаются из стека операндов.

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

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

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

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

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

Примечания

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

bipush

Операция

Положить byte

Формат


bipush
byte

Формы

bipush = 16 (0x10)

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

... →

..., value

Описание

Непосредственный byte расширяется со знаком до int value. Это 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 является значением типа, заданного разрешённым классом, массивом или интерфейсным типом, то стек операндов не изменяется.

Следующие правила используются для определения, является ли ссылка на объект, не являющуюся null, значением типа ссылки T.

  • Если ссылка относится к экземпляру класса C, то:

    • Если T — тип класса D, то ссылка является значением T, если C — D или подклассом D;

    • Если T — тип интерфейса I, то ссылка является значением T, если C реализует I.

  • Если ссылка относится к массиву с типом компонента SC, то:

    • Если T — тип класса, то ссылка является значением T, если T — Object;

    • Если T — тип интерфейса, то ссылка является значением T, если T — Cloneable или java.io.Serializable, как определено загрузчиком Bootstrap-классов (§5.3);

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

      • TC и SC — один и тот же тип;

      • TC — тип класса Object;

      • TC — тип класса или интерфейса, SC — тип класса или интерфейса, и класс или интерфейс, именованный SC, расширяет или реализует класс или интерфейс, именованный TC;

      • SC — тип массива SCC[], и (применив эти правила рекурсивно) ссылка на массив с типом компонента SCC является значением типа TC.

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

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

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

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

Примечания

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

d2f

Операция

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

Формат


d2f

Формы

d2f = 144 (0x90)

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

..., value →

..., result

Описание

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

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

Примечания

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

d2i

Операция

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

Формат


d2i

Формы

d2i = 142 (0x8e)

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

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

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

Описание

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

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

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

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

Примечания

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

d2l

Операция

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

Формат


d2l

Формы

d2l = 143 (0x8f)

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

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

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

Описание

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

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

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

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

Примечания

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

dadd

Операция

Сложить double

Формат


dadd

Формы

dadd = 99 (0x63)

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

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

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

Описание

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

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

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

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

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

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

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

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

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

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

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

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

daload

Операция

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

Формат


daload

Формы

daload = 49 (0x31)

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

..., arrayref, index →

..., value

Описание

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

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

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

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

dastore

Операция

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

Формат


dastore

Формы

dastore = 82 (0x52)

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

..., arrayref, index, value →

...

Описание

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

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

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

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

dcmp<op>

Операция

Сравнение double

Формат


dcmp<op>

Формы

dcmpg = 152 (0x98)

dcmpl = 151 (0x97)

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

..., value1, value2 →

..., result

Описание

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

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

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

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

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

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

Примечания

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

dconst_<d>

Операция

Помещение double-константы

Формат


dconst_<d>

Формы

dconst_0 = 14 (0xe)

dconst_1 = 15 (0xf)

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

... →

..., <d>

Описание

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

END_OF_DOCUMENT_MARKER

ddiv

Операция

Деление

Формат


ddiv

Формы

ddiv = 111 (0x6f)

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

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

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

Описание

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

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

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

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

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

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

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

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

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

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

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

dload

Операция

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

Формат


dload
индекс

Формы

dload = 24 (0x18)

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

... →

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

Описание

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

Примечания

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

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

Описание

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

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

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

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

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

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

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

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

dneg

Операция

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

Формат


dneg

Формы

dneg = 119 (0x77)

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

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

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

Описание

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

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

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

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

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

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

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

drem

Операция

Остаток double

Формат


drem

Формы

drem = 115 (0x73)

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

..., value1, value2 →

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

Описание

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

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

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

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

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

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

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

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

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

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

Примечания

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

dreturn

Операция

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

Формат


dreturn

Формы

dreturn = 175 (0xaf)

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

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

[пусто]

Описание

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

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

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

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

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

dstore

Операция

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

Формат


dstore
индекс

Формы

dstore = 57 (0x39)

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

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

...

Описание

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

Примечания

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

dsub

Операция

Вычитание double

Формат


dsub

Формы

dsub = 103 (0x67)

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

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

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

Описание

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

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

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

dup

Операция

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

Формат


dup

Формы

dup = 89 (0x59)

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

..., value →

..., value, value

Описание

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

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

dup_x1

Операция

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

Формат


dup_x1

Формы

dup_x1 = 90 (0x5a)

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

..., value2, value1 →

..., value1, value2, value1

Описание

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

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

dup_x2

Операция

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

Формат


dup_x2

Формы

dup_x2 = 91 (0x5b)

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

Форма 1:

..., value3, value2, value1 →

..., value1, value3, value2, value1

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

Форма 2:

..., value2, value1 →

..., value1, value2, value1

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

Описание

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

dup2

Операция

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

Формат


dup2

Формы

dup2 = 92 (0x5c)

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

Форма 1:

..., value2, value1 →

..., value2, value1, value2, value1

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

Форма 2:

..., value →

..., value, value

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

Описание

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

dup2_x1

Операция

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

Формат


dup2_x1

Формы

dup2_x1 = 93 (0x5d)

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

Форма 1:

..., value3, value2, value1 →

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

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

Форма 2:

..., value2, value1 →

..., value1, value2, value1

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

Описание

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

dup2_x2

Операция

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

Формат


dup2_x2

Формы

dup2_x2 = 94 (0x5e)

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

Форма 1:

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

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

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

Форма 2:

..., value3, value2, value1 →

..., value1, value3, value2, value1

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

Форма 3:

..., value3, value2, value1 →

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

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

Форма 4:

..., value2, value1 →

..., value1, value2, value1

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

Описание

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

f2d

Операция

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

Формат


f2d

Формы

f2d = 141 (0x8d)

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

..., value →

..., result

Описание

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

Примечания

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

f2i

Операция

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

Формат


f2i

Формы

f2i = 139 (0x8b)

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

..., value →

..., result

Описание

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

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

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

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

Примечания

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

f2l

Операция

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

Формат


f2l

Формы

f2l = 140 (0x8c)

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

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

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

Описание

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

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

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

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

Примечания

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

fadd

Операция

Сложить float

Формат


fadd

Формы

fadd = 98 (0x62)

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

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

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

Описание

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

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

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

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

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

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

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

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

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

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

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

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

faload

Операция

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

Формат


faload

Формы

faload = 48 (0x30)

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

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

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

Описание

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

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

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

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

fastore

Операция

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

Формат


fastore

Формы

fastore = 81 (0x51)

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

..., arrayref, index, value →

...

Описание

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

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

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

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

fcmp<op>

Операция

Сравнение float

Формат


fcmp<op>

Формы

fcmpg = 150 (0x96)

fcmpl = 149 (0x95)

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

..., value1, value2 →

..., result

Описание

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

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

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

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

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

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

Примечания

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

fconst_<f>

Операция

Поместить float

Формат


fconst_<f>

Формы

fconst_0 = 11 (0xb)

fconst_1 = 12 (0xc)

fconst_2 = 13 (0xd)

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

... →

..., <f>

Описание

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

fdiv

Операция

Деление float

Формат


fdiv

Формы

fdiv = 110 (0x6e)

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

..., value1, value2 →

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

Описание

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

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

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

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

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

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

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

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

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

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

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

fload

Операция

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

Формат


fload
index

Формы

fload = 23 (0x17)

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

... →

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

Описание

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 →

..., result

Описание

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

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

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

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

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

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

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

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

fneg

Операция

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

Формат


fneg

Формы

fneg = 118 (0x76)

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

..., value →

..., result

Описание

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

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

Специальные случаи:

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

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

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

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

frem

Операция

Остаток float

Формат


frem

Формы

frem = 114 (0x72)

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

..., value1, value2 →

..., result

Описание

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

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

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

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

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

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

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

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

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

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

Примечания

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

freturn

Операция

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

Формат


freturn

Формы

freturn = 174 (0xae)

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

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

[пусто]

Описание

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

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

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

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

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

fstore

Операция

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

Формат


fstore
индекс

Формы

fstore = 56 (0x38)

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

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

...

Описание

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

Примечания

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

fstore_<n>

Операция

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

Формат


fstore_<n>

Формы

fstore_0 = 67 (0x43)

fstore_1 = 68 (0x44)

fstore_2 = 69 (0x45)

fstore_3 = 70 (0x46)

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

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

...

Описание

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

Примечания

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

fsub

Операция

Вычитание float

Формат


fsub

Формы

fsub = 102 (0x66)

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

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

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

Описание

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

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

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

getfield

Операция

Получить значение поля из объекта

Формат


getfield
indexbyte1
indexbyte2

Формы

getfield = 180 (0xb4)

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

..., objectref →

..., value

Описание

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

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

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

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

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

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

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

Примечания

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

getstatic

Операция

Получить поле из класса

Формат


getstatic
indexbyte1
indexbyte2

Формы

getstatic = 178 (0xb2)

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

..., →

..., value

Описание

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

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

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

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

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

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

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

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

goto

Операция

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

Формат


goto
branchbyte1
branchbyte2

Формы

goto = 167 (0xa7)

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

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

Описание

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

goto_w

Операция

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

Формат


goto_w
branchbyte1
branchbyte2
branchbyte3
branchbyte4

Формы

goto_w = 200 (0xc8)

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

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

Описание

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

Примечания

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

i2b

Операция

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

Формат


i2b

Формы

i2b = 145 (0x91)

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

..., value →

..., result

Описание

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

Примечания

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

i2c

Операция

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

Формат


i2c

Формы

i2c = 146 (0x92)

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

..., value →

..., result

Описание

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

Примечания

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

i2d

Операция

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

Формат


i2d

Формы

i2d = 135 (0x87)

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

..., value →

..., result

Описание

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

Примечания

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

i2f

Операция

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

Формат


i2f

Формы

i2f = 134 (0x86)

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

..., value →

..., result

Описание

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

Примечания

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

i2l

Операция

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

Формат


i2l

Формы

i2l = 133 (0x85)

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

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

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

Описание

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

Примечания

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

i2s

Операция

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

Формат


i2s

Формы

i2s = 147 (0x93)

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

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

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

Описание

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

Примечания

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

iadd

Операция

Сложить int

Формат


iadd

Формы

iadd = 96 (0x60)

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

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

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

Описание

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

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

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

iaload

Операция

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

Формат


iaload

Формы

iaload = 46 (0x2e)

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

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

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

Описание

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

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

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

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

iand

Операция

Побитовое И int

Формат


iand

Формы

iand = 126 (0x7e)

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

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

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

Описание

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

iastore

Операция

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

Формат


iastore

Формы

iastore = 79 (0x4f)

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

..., arrayref, index, value →

...

Описание

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

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

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

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

iconst_<i>

Операция

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

Формат


iconst_<i>

Формы

iconst_m1 = 2 (0x2)

iconst_0 = 3 (0x3)

iconst_1 = 4 (0x4)

iconst_2 = 5 (0x5)

iconst_3 = 6 (0x6)

iconst_4 = 7 (0x7)

iconst_5 = 8 (0x8)

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

... →

..., <i>

Описание

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

Примечания

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

idiv

Операция

Деление int

Формат


idiv

Формы

idiv = 108 (0x6c)

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

..., value1, value2 →

..., result

Описание

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

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

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

if_icmp<cond>

Операция

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

Формат


if_icmp<cond>
branchbyte1
branchbyte2

Формы

if_icmpeq = 159 (0x9f)

if_icmpne = 160 (0xa0)

if_icmplt = 161 (0xa1)

if_icmpge = 162 (0xa2)

if_icmpgt = 163 (0xa3)

if_icmple = 164 (0xa4)

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

..., value1, value2 →

...

Описание

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

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

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

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

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

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

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

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

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

if<cond>

Операция

Ветвление, если int сравнение с нулём успешно

Формат


if<cond>
branchbyte1
branchbyte2

Формы

ifeq = 153 (0x99)

ifne = 154 (0x9a)

iflt = 155 (0x9b)

ifge = 156 (0x9c)

ifgt = 157 (0x9d)

ifle = 158 (0x9e)

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

..., value →

...

Описание

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

  • ifeq успешно, если и только если value = 0

  • ifne успешно, если и только если value ≠ 0

  • iflt успешно, если и только если value < 0

  • ifle успешно, если и только если value ≤ 0

  • ifgt успешно, если и только если value > 0

  • ifge успешно, если и только если value ≥ 0

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

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

ifnonnull

Операция

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

Формат


ifnonnull
branchbyte1
branchbyte2

Формы

ifnonnull = 199 (0xc7)

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

..., value →

...

Описание

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

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

ifnull

Операция

Ветвление, если reference равно null

Формат


ifnull
branchbyte1
branchbyte2

Формы

ifnull = 198 (0xc6)

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

..., value →

...

Описание

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

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

iinc

Операция

Инкремент локальной переменной на константу

Формат


iinc
index
const

Формы

iinc = 132 (0x84)

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

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

Описание

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

Примечания

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

iload

Операция

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

Формат


iload
index

Формы

iload = 21 (0x15)

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

... →

..., value

Описание

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

Примечания

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

iload_<n>

Операция

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

Формат


iload_<n>

Формы

iload_0 = 26 (0x1a)

iload_1 = 27 (0x1b)

iload_2 = 28 (0x1c)

iload_3 = 29 (0x1d)

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

... →

..., value

Описание

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

Примечания

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

imul

Операция

Умножение int

Формат


imul

Формы

imul = 104 (0x68)

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

..., value1, value2 →

..., result

Описание

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

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

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

ineg

Операция

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

Формат


ineg

Формы

ineg = 116 (0x74)

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

..., value →

..., result

Описание

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

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

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

instanceof

Операция

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

Формат


instanceof
indexbyte1
indexbyte2

Формы

instanceof = 193 (0xc1)

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

..., objectref →

..., result

Описание

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

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

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

Проверка, является ли objectref значением заданного типа разрешённого класса, массива или типа интерфейса, производится согласно правилам, указанным для §checkcast.

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

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

Примечания

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

invokedynamic

Операция

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

Формат


invokedynamic
indexbyte1
indexbyte2
0
0

Формы

invokedynamic = 186 (0xba)

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

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

...

Описание

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

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

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

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

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

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

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

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

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

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

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

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

Примечания

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

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

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

invokeinterface

Операция

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

Формат


invokeinterface
indexbyte1
indexbyte2
count
0

Формы

invokeinterface = 185 (0xb9)

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

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

...

Описание

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Примечания

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

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

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

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

invokespecial

Операция

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

Формат


invokespecial
indexbyte1
indexbyte2

Формы

invokespecial = 183 (0xb7)

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

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

...

Описание

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Примечания

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

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

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

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

invokestatic

Операция

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

Формат


invokestatic
indexbyte1
indexbyte2

Формы

invokestatic = 184 (0xb8)

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

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

...

Описание

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Примечания

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

invokevirtual

Операция

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

Формат


invokevirtual
indexbyte1
indexbyte2

Формы

invokevirtual = 182 (0xb6)

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

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

...

Описание

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • objectref;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Примечания

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

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

ior

Операция

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

Формат


ior

Формы

ior = 128 (0x80)

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

..., value1, value2 →

..., result

Описание

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

irem

Операция

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

Формат


irem

Формы

irem = 112 (0x70)

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

..., value1, value2 →

..., result

Описание

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

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

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

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

ireturn

Операция

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

Формат


ireturn

Формы

ireturn = 172 (0xac)

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

..., value →

[пусто]

Описание

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

Прежде чем поместить value в стек операндов рамки вызывающего метода, может потребоваться его преобразование. Если тип возвращаемого значения вызванного метода был byte, char или short, то value преобразуется из int в тип возвращаемого значения, как если бы выполнялись i2b, i2c или i2s соответственно. Если тип возвращаемого значения вызванного метода был boolean, то value сужается с int до boolean путём взятия битовой И от value и 1.

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

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

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

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

ishl

Операция

Сдвиг влево int

Формат


ishl

Формы

ishl = 120 (0x78)

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

..., value1, value2 →

..., result

Описание

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

Примечания

Это эквивалентно (даже если происходит переполнение) умножению на 2 в степени s. Расстояние сдвига фактически используется всегда в диапазоне от 0 до 31 включительно, как если бы value2 подвергалось побитовому логическому И с маской 0x1f.

END_OF_DOCUMENT_MARKER

ishr

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

Арифметический сдвиг вправо int

Формат


ishr

Формы

ishr = 122 (0x7a)

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

..., value1, value2 →

..., result

Описание

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

Примечания

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

istore

Операция

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

Формат


istore
index

Формы

istore = 54 (0x36)

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

..., value →

...

Описание

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

Примечания

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

istore_<n>

Операция

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

Формат


istore_<n>

Формы

istore_0 = 59 (0x3b)

istore_1 = 60 (0x3c)

istore_2 = 61 (0x3d)

istore_3 = 62 (0x3e)

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

..., value →

...

Описание

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

Примечания

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

isub

Операция

Вычитание int

Формат


isub

Формы

isub = 100 (0x64)

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

..., value1, value2 →

..., result

Описание

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

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

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

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

iushr

Операция

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

Формат


iushr

Формы

iushr = 124 (0x7c)

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

..., value1, value2 →

..., result

Описание

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

Примечания

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

ixor

Операция

Булево XOR int

Формат


ixor

Формы

ixor = 130 (0x82)

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

..., value1, value2 →

..., result

Описание

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

jsr

Операция

Переход в подпрограмму

Формат


jsr
branchbyte1
branchbyte2

Формы

jsr = 168 (0xa8)

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

... →

..., address

Описание

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

Примечания

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

В реализации компилятора Oracle для языка программирования Java до Java SE 6 инструкция jsr использовалась с инструкцией ret для реализации блока finally (§3.13, §4.10.2.5).

jsr_w

Операция

Переход в подпрограмму (смещение широкого индекса)

Формат


jsr_w
branchbyte1
branchbyte2
branchbyte3
branchbyte4

Формы

jsr_w = 201 (0xc9)

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

... →

..., address

Описание

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

Примечания

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

В реализации компилятора Oracle для языка программирования Java до Java SE 6 инструкция jsr_w использовалась с инструкцией ret для реализации блока finally (§3.13, §4.10.2.5).

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

l2d

Операция

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

Формат


l2d

Формы

l2d = 138 (0x8a)

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

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

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

Описание

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

Примечания

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

l2f

Операция

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

Формат


l2f

Формы

l2f = 137 (0x89)

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

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

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

Описание

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

Примечания

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

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

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

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

Описание

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

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

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

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

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

lcmp

Операция

Сравнение long

Формат


lcmp

Формы

lcmp = 148 (0x94)

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

..., value1, value2 →

..., result

Описание

Оба значения value1 и value2 должны быть типа long. Они оба извлекаются из стека операндов, и выполняется сравнение целых чисел со знаком. Если value1 больше value2, в стек операндов помещается значение 1. Если value1 равно value2, в стек операндов помещается значение 0. Если value1 меньше value2, в стек операндов помещается значение -1.

lconst_<l>

Операция

Поместить константу long

Формат


lconst_<l>

Формы

lconst_0 = 9 (0x9)

lconst_1 = 10 (0xa)

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

... →

..., <l>

Описание

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

ldc

Операция

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

Формат


ldc
index

Формы

ldc = 18 (0x12)

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

... →

..., value

Описание

index — это беззнаковый байт, который должен быть допустимым индексом в пуле постоянных времени выполнения текущего класса (§2.5.5). Элемент пула постоянных времени выполнения по индексу index должен быть загружаемым (§5.1), и не должен быть ни одним из следующих:

  • Численное значение типа long или double.

  • Символическая ссылка на динамически вычисляемое значение, у которого полевое описание равно J (обозначающее long) или D (обозначающее double).

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

В противном случае, если элемент пула постоянных времени выполнения — строковое значение, то есть ссылка на экземпляр класса String, то value, ссылка на этот экземпляр, помещается в стек операндов.

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

В противном случае, элемент пула постоянных времени выполнения — символьная ссылка на тип метода, дескриптор метода или динамически вычисляемое значение. Символьная ссылка разрешается (§5.4.3.5, §5.4.3.6) и value, результат разрешения, помещается в стек операндов.

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

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

ldc_w

Операция

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

Формат


ldc_w
indexbyte1
indexbyte2

Формы

ldc_w = 19 (0x13)

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

... →

..., value

Описание

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

  • Численное значение типа long или double.

  • Символическая ссылка на динамически вычисляемое значение, у которого полевое описание равно J (обозначающее long) или D (обозначающее double).

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

В противном случае, элемент пула постоянных времени выполнения — символьная ссылка на класс, интерфейс, тип метода, дескриптор метода или динамически вычисляемое значение. Он разрешается, и value определяется и помещается в стек операндов согласно правилам для инструкции ldc.

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

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

Примечания

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

ldc2_w

Операция

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

Формат


ldc2_w
indexbyte1
indexbyte2

Формы

ldc2_w = 20 (0x14)

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

... →

..., value

Описание

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

  • Численная константа типа long или double.

  • Символическая ссылка на динамически вычисляемую константу, чьё описание поля — J (обозначающее long) или D (обозначающее double).

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

В противном случае элемент пула констант — это символическая ссылка на динамически вычисляемую константу. Символическая ссылка разрешается (§5.4.3.6) и значение value, результат разрешения, выталкивается на стек операндов.

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

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

Примечания

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

ldiv

Операция

Деление long

Формат


ldiv

Формы

ldiv = 109 (0x6d)

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

..., value1, value2 →

..., result

Описание

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

Деление long округляет к нулю; то есть, частное, получаемое для 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)

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

... →

..., value

Описание

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)

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

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

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

Описание

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

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

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

lneg

Операция

Отрицание long

Формат


lneg

Формы

lneg = 117 (0x75)

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

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

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

Описание

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

Для значений 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 должно быть от 0 до 3 байтов заполнения, таким образом, 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)

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

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

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

Описание

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

lrem

Операция

Остаток long

Формат


lrem

Формы

lrem = 113 (0x71)

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

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

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

Описание

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

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

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

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

lreturn

Операция

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

Формат


lreturn

Формы

lreturn = 173 (0xad)

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

..., value →

[пусто]

Описание

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

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

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

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

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

lshl

Операция

Сдвиг влево long

Формат


lshl

Формы

lshl = 121 (0x79)

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

..., value1, value2 →

..., result

Описание

value1 должен быть типа long, а value2 должен быть типа int. Значения извлекаются из стека операндов. Результат 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 помещается в стек операндов.

Примечания

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

lstore

Операция

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

Формат


lstore
index

Формы

lstore = 55 (0x37)

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

..., value →

...

Описание

index - беззнаковый байт. index и index+1 должны быть индексами в массиве локальных переменных текущей рамки (§2.6). value на вершине стека операндов должен быть типа long. Он извлекается из стека операндов, а локальные переменные по индексам index и index+1 устанавливаются в value.

Примечания

Инструкция lstore может использоваться совместно с инструкцией wide (§wide) для доступа к локальной переменной с использованием двубайтового беззнакового индекса.

lstore_<n>

Операция

Сохранить long в локальную переменную

Формат


lstore_<n>

Формы

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_<n> аналогична инструкции lstore с индексом <n>, за исключением того, что операнд <n> неявный.

lsub

Операция

Вычитание long

Формат


lsub

Формы

lsub = 101 (0x65)

Стек операндов

..., значение1, значение2 →

..., результат

Описание

Значение1 и Значение2 должны быть типа long. Значения извлекаются из стека операндов. Результат равен Значение1 - Значение2. Результат помещается в стек операндов.

При вычитании long результат аналогичен a+(-b). При вычитании long из нуля результат эквивалентен отрицанию.

Результат — 64 младших бита истинного математического результата в достаточно широком формате со знаком дополнения, представленного как значение типа long. Если происходит переполнение, то знак результата может отличаться от знака математической разницы двух значений.

Несмотря на возможность переполнения, выполнение инструкции lsub никогда не вызывает исключения во время выполнения.

lushr

Операция

Логическое сдвиг вправо long

Формат


lushr

Формы

lushr = 125 (0x7d)

Стек операндов

..., значение1, значение2 →

..., результат

Описание

Значение1 должно быть типа long, а Значение2 — типа int. Значения извлекаются из стека операндов. Вычисляется результат путём логического сдвига значение1 вправо на s бит (с расширением нулями), где s — значение 6 младших битов значение2. Результат помещается в стек операндов.

Примечания

Если значение1 положительно, а s равно значение2 & 0x3f, результат совпадает с результатом значение1 >> s; если значение1 отрицательно, результат равен значению выражения (значение1 >> s) + (2L << ~s). Добавление (2L << ~s) компенсирует распространяемый бит знака. Расстояние сдвига, фактически используемое, всегда находится в диапазоне от 0 до 63 включительно.

lxor

Операция

Булево XOR long

Формат


lxor

Формы

lxor = 131 (0x83)

Стек операндов

..., значение1, значение2 →

..., результат

Описание

Значение1 и Значение2 должны быть типа long. Они извлекаются из стека операндов. Результат вычисляется как побитовое исключающее ИЛИ значение1 и значение2. Результат помещается в стек операндов.

END_OF_DOCUMENT_MARKER

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 применяет правила структурированной блокировки, описанные в §2.11.10, и если второе из этих правил нарушается выполнением данной инструкции monitorexit, то monitorexit генерирует исключение IllegalMonitorStateException.

Примечания

Одна или несколько инструкций monitorexit могут использоваться с инструкцией monitorenter (§monitorenter) для реализации оператора блокировки в языке программирования Java (§3.14). Инструкции monitorenter и monitorexit не используются в реализации методов synchronized, хотя они могут использоваться для предоставления эквивалентной семантики блокировки.

Виртуальная машина Java поддерживает исключения, возникающие внутри методов synchronized и операторов synchronized, по-разному:

  • Выход из монитора при нормальном завершении метода synchronized обрабатывается инструкциями возврата виртуальной машины Java. Выход из монитора при внезапном завершении метода synchronized неявно обрабатывается инструкцией athrow виртуальной машины Java.

  • При возникновении исключения внутри оператора synchronized, выход из монитора, в который входил до выполнения оператора synchronized, достигается с помощью механизма обработки исключений виртуальной машины Java (§3.14).

multianewarray

Операция

Создание многомерного массива

Формат


multianewarray
indexbyte1
indexbyte2
dimensions

Формы

multianewarray = 197 (0xc5)

Стек операндов

..., count1, [count2, ...] →

..., arrayref

Описание

Операнд dimensions — это беззнаковый байт, который должен быть больше или равен 1. Он представляет количество измерений создаваемого массива. Стек операндов должен содержать dimensions значений. Каждое такое значение представляет количество компонентов в измерении создаваемого массива, должно быть типа int и должно быть неотрицательным. count1 — желаемая длина в первом измерении, count2 — во втором и т. д.

Все значения count извлекаются из стека операндов. Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на класс, массив или тип интерфейса. Имя класса, массива или типа интерфейса разрешается (§5.4.3.1). Результирующий элемент должен быть типом класса массива с размерностью, большей или равной dimensions.

Новый многомерный массив указанного типа выделяется из кучи с автоматическим сбором мусора. Если какое-либо значение count равно нулю, последующие измерения не выделяются. Компоненты массива в первом измерении инициализируются подмассивами типа второго измерения и так далее. Компоненты последнего выделенного измерения массива инициализируются значениями по умолчанию (§2.3, §2.4) для типа элемента типа массива. Ссылка arrayref на новый массив помещается на стек операндов.

Исключения при связывании

При разрешении символической ссылки на класс, массив или тип интерфейса могут быть выброшены любые исключения, описанные в §5.4.3.1.

В противном случае, если текущий класс не имеет разрешения на доступ к типу элемента разрешенного класса массива, multianewarray выбрасывает исключение IllegalAccessError.

Исключение во время выполнения

В противном случае, если какое-либо из значений dimensions на стеке операндов меньше нуля, инструкция multianewarray выбрасывает исключение NegativeArraySizeException.

Примечания

Для создания массива с одним измерением может быть эффективнее использовать newarray или anewarray (§newarray, §anewarray).

Класс массива, на который ссылается постоянный пул времени выполнения, может иметь больше измерений, чем операнд dimensions инструкции multianewarray. В этом случае создаются только первые dimensions измерений массива.

new

Операция

Создание нового объекта

Формат


new
indexbyte1
indexbyte2

Формы

new = 187 (0xbb)

Стек операндов

... →

..., objectref

Описание

Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на класс или тип интерфейса. Имя класса или типа интерфейса разрешается (§5.4.3.1) и должно быть типом класса. Память для нового экземпляра этого класса выделяется из кучи с автоматическим сбором мусора, а переменные экземпляра нового объекта инициализируются их значениями по умолчанию (§2.3, §2.4). Ссылка objectref на экземпляр помещается на стек операндов.

При успешном разрешении класса он инициализируется, если еще не был инициализирован (§5.5).

Исключения при связывании

При разрешении символической ссылки на класс или тип интерфейса могут быть выброшены любые исключения, описанные в §5.4.3.1.

В противном случае, если символическая ссылка на класс или тип интерфейса разрешается в интерфейс или абстрактный класс, new выбрасывает исключение InstantiationError.

Исключение во время выполнения

В противном случае, если выполнение этой инструкции new вызывает инициализацию ссылаемого класса, new может выбросить исключение Error, как описано в JLS §15.9.4.

Примечания

Инструкция new не полностью создает новый экземпляр; создание экземпляра не завершается до тех пор, пока метод инициализации экземпляра (§2.9.1) не будет вызван на неинициализированном экземпляре.

newarray

Операция

Создание нового массива

Формат


newarray
atype

Формы

newarray = 188 (0xbc)

Стек операндов

..., count →

..., arrayref

Описание

Значение count должно быть типа int. Оно извлекается из стека операндов. Значение count представляет количество элементов в создаваемом массиве.

atype — это код, указывающий тип создаваемого массива. Он должен принимать одно из следующих значений:

Таблица 6.5.newarray-A. Коды типов массивов

Тип массива atype
T_BOOLEAN 4
T_CHAR 5
T_FLOAT 6
T_DOUBLE 7
T_BYTE 8
T_SHORT 9
T_INT 10
T_LONG 11

Создается новый массив, компоненты которого имеют тип atype и длину count, выделенный из кучи сборщика мусора. Ссылка arrayref на этот новый объект массива помещается в стек операндов. Каждый элемент нового массива инициализируется значением по умолчанию (§2.3, §2.4) для типа элемента типа массива.

Исключение во время выполнения

Если count меньше нуля, newarray выбрасывает исключение NegativeArraySizeException.

Примечания

В реализации виртуальной машины Java Oracle, массивы типа boolean (atype равно T_BOOLEAN) хранятся как массивы 8-битовых значений и обрабатываются инструкциями baload и bastore (§baload, §bastore), которые также обращаются к массивам типа byte. Другие реализации могут реализовывать упакованные boolean массивы; инструкции baload и bastore по-прежнему должны использоваться для доступа к этим массивам.

nop

Операция

Не делать ничего

Формат


nop

Формы

nop = 0 (0x0)

Стек операндов

Без изменений

Описание

Не делать ничего.

pop

Операция

Извлечь верхнее значение из стека операндов

Формат


pop

Формы

pop = 87 (0x57)

Стек операндов

..., value →

...

Описание

Извлечь верхнее значение из стека операндов.

Инструкция pop не должна использоваться, если value не является значением вычислительного типа категории 1 (§2.11.1).

pop2

Операция

Извлечь одно или два верхних значения из стека операндов

Формат


pop2

Формы

pop2 = 88 (0x58)

Стек операндов

Форма 1:

..., value2, value1 →

...

где каждое из value1 и value2 — значение вычислительного типа категории 1 (§2.11.1).

Форма 2:

..., value →

...

где value — значение вычислительного типа категории 2 (§2.11.1).

Описание

Извлечь одно или два верхних значения со стека операндов.

putfield

Операция

Установка поля в объект

Формат


putfield
indexbyte1
indexbyte2

Формы

putfield = 181 (0xb5)

Операционная стопка

..., objectref, value →

...

Описание

Беззнаковые значения indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на поле (§5.1), которая содержит имя и дескриптор поля, а также символическую ссылку на класс, в котором находится поле. Ссылаемое поле разрешается (§5.4.3.2).

Тип хранимого value инструкцией putfield должен быть совместим с дескриптором ссылаемого поля (§4.3.2). Если тип дескриптора поля равен boolean, byte, char, short или int, то value должно быть int. Если тип дескриптора поля равен float, long или double, то value должно быть float, long или double соответственно. Если тип дескриптора поля является типом класса или массива, то value должно быть значением типа дескриптора поля. Если поле является final, оно должно быть объявлено в текущем классе, и инструкция должна выполняться в методе инициализации экземпляра текущего класса (§2.9.1).

Значения value и objectref извлекаются из операционной стопки.

objectref должен быть типа reference, но не типа массива.

Если value имеет тип int, а тип дескриптора поля — один из byte, char, short или boolean, то значение value преобразуется в тип дескриптора поля следующим образом. Если тип дескриптора поля равен byte, char или short, то значение value усекается до значения типа дескриптора поля, value'. Если тип дескриптора поля равен boolean, то значение value сужается путем взятия побитового И значения value и 1, в результате чего получается value'. Ссылаемое поле в objectref устанавливается в значение value'.

В противном случае, ссылаемое поле в objectref устанавливается в значение value.

Исключения при связывании

Во время разрешения символической ссылки на поле могут быть выброшены любые исключения, относящиеся к разрешению поля (§5.4.3.2).

В противном случае, если разрешенное поле является static полем, putfield генерирует исключение IncompatibleClassChangeError.

В противном случае, если разрешенное поле является final, оно должно быть объявлено в текущем классе, и инструкция должна выполняться в методе инициализации экземпляра текущего класса. В противном случае генерируется исключение IllegalAccessError.

Исключение во время выполнения

В противном случае, если objectref является null, инструкция putfield генерирует исключение NullPointerException.

putstatic

Операция

Установка статического поля в классе

Формат


putstatic
indexbyte1
indexbyte2

Формы

putstatic = 179 (0xb3)

Операционный стек

..., значение →

...

Описание

Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пул постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Запись в пуле постоянных времени выполнения по этому индексу должна быть символической ссылкой на поле (§5.1), которая содержит имя и дескриптор поля, а также символическую ссылку на класс или интерфейс, в котором находится поле. Ссылка на поле разрешается (§5.4.3.2).

После успешного разрешения поля, класс или интерфейс, объявивший разрешенное поле, инициализируется, если этот класс или интерфейс еще не был инициализирован (§5.5).

Тип значение, хранимый инструкцией putstatic, должен быть совместим с дескриптором ссылки на поле (§4.3.2). Если тип дескриптора поля равен boolean, byte, char, short или int, то значение должно быть int. Если тип дескриптора поля равен float, long или double, то значение должно быть float, long или double соответственно. Если тип дескриптора поля является типом класса или типом массива, то значение должно быть значением типа дескриптора поля. Если поле является final, оно должно быть объявлено в текущем классе или интерфейсе, а инструкция должна находиться в методе инициализации класса или интерфейса текущего класса или интерфейса (§2.9.2).

Значение значение извлекается из операционного стека.

Если значение имеет тип int, а тип дескриптора поля является одним из byte, char, short или boolean, то значение значение преобразуется к типу дескриптора поля следующим образом. Если тип дескриптора поля равен byte, char или short, то значение значение усекается до значения типа дескриптора поля, значение'. Если тип дескриптора поля равен boolean, то значение значение сужается путём побитового И значение и 1, что приводит к значение'. Ссылка на поле в классе или интерфейсе устанавливается в значение'.

В противном случае ссылка на поле в классе или интерфейсе устанавливается в значение.

Исключения при связывании

Во время разрешения символической ссылки на поле класса или интерфейса могут быть выброшены любые исключения, связанные с разрешением поля (§5.4.3.2).

В противном случае, если разрешенное поле не является полем класса (class) или интерфейса, putstatic выбросит исключение IncompatibleClassChangeError.

В противном случае, если разрешенное поле является final, оно должно быть объявлено в текущем классе или интерфейсе, а инструкция должна выполняться в методе инициализации класса или интерфейса текущего класса или интерфейса. В противном случае выбрасывается исключение IllegalAccessError.

Исключение во время выполнения

В противном случае, если выполнение этой инструкции putstatic вызывает инициализацию ссылаемого класса или интерфейса, putstatic может выбросить исключение Error, как подробно описано в §5.5.

Примечания

Инструкция putstatic может использоваться только для установки значения поля интерфейса во время инициализации этого поля. Поля интерфейса могут быть присвоены только один раз при выполнении выражения инициализации переменной интерфейса во время инициализации интерфейса (§5.5, JLS §9.3.1).

ret

Операция

Возврат из подпрограммы

Формат


ret
index

Формы

ret = 169 (0xa9)

Операционный стек

Без изменений

Описание

index — это беззнаковый байт от 0 до 255 включительно. Локальная переменная по индексу index в текущей рамке (§2.6) должна содержать значение типа returnAddress. Содержимое локальной переменной записывается в регистр виртуальной машины Java, и выполнение продолжается оттуда.

Примечания

Обратите внимание, что jsr (§jsr) помещает адрес в операционный стек, а ret получает его из локальной переменной. Эта асимметрия намеренная.

В реализации компилятора Oracle для языка программирования Java до Java SE 6 инструкция ret использовалась с инструкциями jsr и jsr_w (§jsr, §jsr_w) в реализации блока finally (§3.13, §4.10.2.5).

Инструкцию ret не следует путать с инструкцией return (§return). Инструкция return возвращает управление из метода его вызывателю, не передавая ему никакого значения.

Код операции ret может быть использован совместно с инструкцией wide (§wide) для доступа к локальной переменной с использованием двубайтового беззнакового индекса.

return

Операция

Возвращение void из метода

Формат


return

Формы

return = 177 (0xb1)

Стек операндов

... →

[пусто]

Описание

Текущий метод должен иметь тип возвращаемого значения void. Если текущий метод является методом synchronized, монитор, введённый или повторно введённый при вызове метода, обновляется и, возможно, выходит из него так, как если бы выполнялась инструкция monitorexit (§monitorexit) в текущем потоке. Если исключение не выбрасывается, любые значения в стеке операндов текущей рамки (§2.6) отбрасываются.

Затем интерпретатор возвращает управление вызывающему методу, восстанавливая рамку вызывающего метода.

Исключения во время выполнения

Если реализация Java Virtual Machine не выполняет правила структурированного блокирования, описанные в §2.11.10, то, если текущий метод является методом synchronized, а текущий поток не является владельцем монитора, введённого или повторно введённого при вызове метода, return выбрасывает IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит инструкцию monitorexit, но не monitorenter для объекта, на котором метод synchronized.

В противном случае, если реализация Java Virtual Machine выполняет правила структурированного блокирования, описанные в §2.11.10, и если первое из этих правил нарушается при вызове текущего метода, то return выбрасывает IllegalMonitorStateException.

saload

Операция

Загрузка short из массива

Формат


saload

Формы

saload = 53 (0x35)

Стек операндов

..., arrayref, index →

..., value

Описание

arrayref должен быть типа reference и должен ссылаться на массив, компоненты которого являются типа short. index должен быть типа int. И arrayref, и index извлекаются из стека операндов. Компонент массива в позиции index извлекается и расширяется со знаком до int value. Это value помещается в стек операндов.

Исключения во время выполнения

Если arrayref является null, saload выбрасывает NullPointerException.

В противном случае, если index не находится в пределах границ массива, на который ссылается arrayref, инструкция saload выбрасывает ArrayIndexOutOfBoundsException.

sastore

Операция

Сохранение в массив short

Формат


sastore

Формы

sastore = 86 (0x56)

Стек операндов

..., arrayref, index, value →

...

Описание

arrayref должен быть типа reference и должен ссылаться на массив, компоненты которого являются типа short. index и value должны быть типа int. arrayref, index и value извлекаются из стека операндов. Значение value усекается до short и сохраняется в качестве компонента массива по индексу index.

Исключения во время выполнения

Если arrayref является null, sastore выбрасывает NullPointerException.

В противном случае, если index не находится в пределах границ массива, на который ссылается arrayref, инструкция sastore выбрасывает ArrayIndexOutOfBoundsException.

sipush

Операция

Помещение short

Формат


sipush
byte1
byte2

Формы

sipush = 17 (0x11)

Стек операндов

... →

..., value

Описание

Непосредственные беззнаковые значения byte1 и byte2 собираются в промежуточное short, где значение short равно (byte1 << 8) | byte2. Промежуточное значение расширяется со знаком до int value. Это value помещается в стек операндов.

swap

Операция

Поменять местами верхние два значения стека операндов

Формат


swap

Формы

swap = 95 (0x5f)

Стек операндов

..., value2, value1 →

..., value1, value2

Описание

Поменяйте местами два верхних значения в стеке операндов.

Инструкцию swap нельзя использовать, если value1 и value2 не являются значениями вычислительного типа категории 1 (§2.11.1).

Примечания

В Java Virtual Machine нет инструкции для перестановки операндов вычислительных типов категории 2.

tableswitch

Операция

Обращение к таблице переходов по индексу и переход

Формат


tableswitch
<0-3 byte pad>
defaultbyte1
defaultbyte2
defaultbyte3
defaultbyte4
lowbyte1
lowbyte2
lowbyte3
lowbyte4
highbyte1
highbyte2
highbyte3
highbyte4
jump offsets...

Формы

tableswitch = 170 (0xaa)

Стек операндов

..., index →

...

Описание

Инструкция tableswitch имеет переменную длину. Сразу после кода операции tableswitch должны следовать от нуля до трёх байтов заполнения, так чтобы defaultbyte1 начинался по адресу, кратному четырём байтам с начала текущего метода (с кода первой инструкции). Сразу после заполнения идут байты, представляющие три целых 32-битных значения: default, low и high. Непосредственно за ними следуют байты, представляющие серию из high - low + 1 целых 32-битных смещений. Значение low должно быть меньше или равно high. Последующие high - low + 1 целых 32-битных смещений интерпретируются как таблица переходов с нулевым индексом. Каждое из этих целых 32-битных значений строится как (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4.

Значение index должно быть типа int и извлекается из стека операндов. Если index меньше low или index больше high, то целевой адрес рассчитывается, добавляя default к адресу кода операции этой инструкции tableswitch. В противном случае извлекается смещение в позиции index - low таблицы переходов. Целевой адрес рассчитывается, добавляя это смещение к адресу кода операции этой инструкции tableswitch. После этого выполнение продолжается по целевому адресу.

Целевой адрес, который можно вычислить из каждого смещения таблицы переходов, а также тот, который можно вычислить из default, должен соответствовать адресу кода операции инструкции внутри метода, содержащего эту инструкцию tableswitch.

Примечания

Требование выравнивания 4-байтовых операндов инструкции tableswitch гарантирует 4-байтовое выравнивание этих операндов только в том случае, если метод, содержащий инструкцию tableswitch, начинается на границе 4 байт.

wide

Операция

Увеличение индекса локальной переменной на дополнительные байты

Формат 1


wide
<opcode>
indexbyte1
indexbyte2

где <opcode> — одно из iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore или ret

Формат 2


wide
iinc
indexbyte1
indexbyte2
constbyte1
constbyte2

Формы

wide = 196 (0xc4)

Стек операндов

Такой же, как у модифицированной инструкции

Описание

Инструкция wide изменяет поведение другой инструкции. Она принимает один из двух форматов, в зависимости от изменяемой инструкции. Первый формат инструкции wide модифицирует одну из инструкций iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore или ret (§iload, §fload, §aload, §lload, §dload, §istore, §fstore, §astore, §lstore, §dstore, §ret). Второй формат применяется только к инструкции iinc (§iinc).

В любом случае, сам оператор wide в скомпилированном коде следует за оператором инструкции, которую wide изменяет. В любом формате за модифицированным оператором следуют два беззнаковых байта indexbyte1 и indexbyte2, которые собираются в 16-битный беззнаковый индекс локальной переменной в текущем фрейме (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Вычисленный индекс должен соответствовать индексу в массиве локальных переменных текущего фрейма. В случае модификации инструкции 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