Глава 6. Набор инструкций виртуальной машины Java
Оглавление
-
- 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
- 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
- istore_
Инструкция виртуальной машины Java состоит из кода операции, определяющего выполняемое действие, и нуля или более операндов, содержащих значения, над которыми нужно выполнить операции. В этой главе подробно описывается формат каждой инструкции виртуальной машины Java и выполняемая ею операция.
Описание каждой инструкции всегда дается в контексте кода виртуальной машины Java, который удовлетворяет статическим и структурным ограничениям §4 (Формат файла class). В описании отдельных инструкций виртуальной машины Java часто указывается, что какая-то ситуация «должна» или «не должна» иметь место: «Значение value2 должно быть типа int». Ограничения §4 (Формат файла class) гарантируют, что все такие ожидания будут выполнены. Если какое-либо ограничение («должен» или «не должен») в описании инструкции не выполняется во время выполнения, поведение виртуальной машины Java не определено.
Виртуальная машина Java проверяет, что код виртуальной машины Java удовлетворяет статическим и структурным ограничениям во время компоновки, используя верификатор файла class (§4.10). Таким образом, виртуальная машина Java будет пытаться выполнить только код из допустимых файлов class.
Выполнение проверки во время компоновки является привлекательным, так как проверки выполняются только один раз, существенно сокращая объем работы, который должен быть выполнен во время выполнения. Возможны и другие стратегии реализации, при условии их соответствия Спецификации языка Java, издание Java SE 21 и Спецификации виртуальной машины Java, издание Java SE 21.
Помимо кодов операций инструкций, указанных позже в этой главе, которые используются в файлах class (§4 (Формат файла class)), три кода операций зарезервированы для внутреннего использования реализацией виртуальной машины Java. Если в будущем набор инструкций виртуальной машины Java будет расширен, эти зарезервированные коды операций гарантированно не будут использоваться.
Два из зарезервированных кодов операций, номера 254 (0xfe) и 255 (0xff), имеют мнемоники impdep1 и impdep2 соответственно. Эти инструкции предназначены для предоставления «задних дверей» или ловушек для функциональности, специфичной для реализации, реализованной в программном и аппаратном обеспечении соответственно.
Третий зарезервированный код операции, номер 202 (0xca), имеет мнемонику breakpoint и предназначен для использования отладчиками для реализации точек останова.
Хотя эти коды операций зарезервированы, они могут быть использованы только внутри реализации виртуальной машины Java. Они не могут появляться в действительных файлах class. Такие инструменты, как отладчики или генераторы JIT-кода (§2.13), которые могут напрямую взаимодействовать с кодом виртуальной машины Java, который уже был загружен и выполнен, могут встретить эти коды операций. Такие инструменты должны пытаться корректно работать, если они встретят любую из этих зарезервированных инструкций.
Реализация Java виртуальной машины выбрасывает объект, являющийся экземпляром подкласса класса VirtualMachineError, когда внутренняя ошибка или ограничение ресурсов препятствуют ей в реализации семантики, описанной в этой главе. Данный документ не может предсказать, где могут возникнуть внутренние ошибки или ограничения ресурсов, и не предписывает точное время их сообщения. Таким образом, любой из подклассов VirtualMachineError, определенных ниже, может быть сгенерирован в любое время во время работы Java виртуальной машины:
-
InternalError: В реализации Java виртуальной машины произошла внутренняя ошибка из-за сбоя в программном обеспечении, реализующем виртуальную машину, сбоя в программном обеспечении базовой хост-системы или сбоя в аппаратном обеспечении. Эта ошибка передается асинхронно (§2.10) при обнаружении и может возникнуть в любой точке программы. -
OutOfMemoryError: Реализация Java виртуальной машины исчерпала виртуальную или физическую память, и автоматический менеджер памяти не смог вернуть достаточно памяти для удовлетворения запроса на создание объекта. -
StackOverflowError: Реализация Java виртуальной машины исчерпала стек памяти для потока, обычно потому, что поток выполняет неограниченное количество рекурсивных вызовов в результате сбоя в выполняемой программе. -
UnknownError: Произошла ошибка или исключение, но реализация Java виртуальной машины не может сообщить об actual исключении или ошибке.
Инструкции Java виртуальной машины представлены в этой главе записями следующего вида, в алфавитном порядке и на новой странице для каждой записи.
мнемоника
Операция
Краткое описание инструкции
Формат
мнемоника
операнд1
операнд2
...
Формы
мнемоника = код операции
Стек операндов
..., значение1, значение2 →
..., значение3
Описание
Более подробное описание ограничений содержимого стека операндов или записей константного пула, выполняемой операции, типа результатов и т. д.
Исключения при связывании
Если какие-либо исключения при связывании могут быть сгенерированы в результате выполнения этой инструкции, они указаны по одной на строке в порядке их возникновения.
Исключения во время выполнения
Если какие-либо исключения во время выполнения могут быть сгенерированы при выполнении инструкции, они указаны по одной на строке в порядке их возникновения.
Помимо исключений при связывании и во время выполнения, если таковые имеются, данная инструкция не должна генерировать никаких исключений во время выполнения, кроме экземпляров VirtualMachineError или его подклассов.
Примечания
Комментарии, которые не являются строго частью спецификации инструкции, выводятся как примечания в конце описания.
Каждая ячейка в диаграмме формата инструкции представляет собой один 8-битовый байт. Мемоника инструкции — это ее имя. Ее код операции — ее числовое представление, приведенное в десятичном и шестнадцатеричном форматах. Только числовое представление фактически присутствует в коде Java виртуальной машины в файле class.
Обратите внимание, что существуют «операнды», генерируемые во время компиляции и встроенные в инструкции Java виртуальной машины, а также «операнды», вычисляемые во время выполнения и предоставляемые в стеке операндов. Несмотря на то, что они поступают из разных источников, все эти операнды представляют собой одно и то же: значения, над которыми будет выполняться инструкция Java виртуальной машины. Используя неявное получение многих операндов из стека операндов, а не их явное представление в скомпилированном коде в виде дополнительных байтов операндов, номеров регистров и т. д., код Java виртуальной машины остается компактным.
Некоторые инструкции представлены как члены семейства родственных инструкций, имеющих общее описание, формат и диаграмму стека операндов. Как таковое, семейство инструкций включает несколько кодов операций и мнемоник; в диаграмме формата инструкции появляется только мнемоника семейства, а отдельный ряд форм перечисляет все мнемоники и коды операций членов. Например, строка Формы для семейства инструкций lconst_<l>, дающая информацию о мнемонике и коде операции для двух инструкций в этом семействе (lconst_0 и lconst_1), выглядит следующим образом:
lconst_0 = 9 (0x9)
lconst_1 = 10 (0xa)
В описании инструкций Java виртуальной машины воздействие выполнения инструкции на стек операндов (§2.6.2) текущей фрейма (§2.6) представлено текстово, со стеком, возрастающим слева направо, и каждым значением, представленным отдельно. Таким образом,
..., значение1, значение2 →
..., результат
показывает операцию, которая начинается с значение2 на вершине стека операндов, а значение1 непосредственно под ним. В результате выполнения инструкции значение1 и значение2 извлекаются из стека операндов и заменяются значением результат, которое было вычислено инструкцией. Остальная часть стека операндов, представленная многоточием (...), не затрагивается выполнением инструкции.
Значения типов long и double представлены одной записью в стеке операндов.
В первом издании спецификации Java® виртуальной машины значения в стеке операндов типов long и double в диаграмме стека представлялись двумя записями.
aaload
Операция
Загрузка reference из массива
Формат
aaload
Формы
aaload = 50 (0x32)
Стек операндов
..., arrayref, index →
..., value
Описание
arrayref должен иметь тип reference и должен ссылаться на массив, компоненты которого имеют тип reference. index должен иметь тип int. Оба arrayref и index извлекаются из стека операндов. Значение value компонента массива по индексу index извлекается и помещается в стек операндов.
Исключения во время выполнения
Если arrayref является null, aaload вызывает исключение NullPointerException.
В противном случае, если index выходит за пределы массива, на который ссылается arrayref, инструкция aaload вызывает исключение ArrayIndexOutOfBoundsException.
aastore
Операция
Запись в массив reference
Формат
aastore
Формы
aastore = 83 (0x53)
Стек операндов
..., arrayref, index, value →
...
Описание
arrayref должен иметь тип reference и должен ссылаться на массив, компоненты которого имеют тип reference. index должен иметь тип int, а value должен иметь тип reference. arrayref, index и value извлекаются из стека операндов.
Если value является null, то value сохраняется как компонент массива по индексу index.
В противном случае, value не является null. Если тип value совместим с типом компонентов массива, на который ссылается arrayref, то value сохраняется как компонент массива по индексу index.
Следующие правила используются для определения того, является ли value, которое не является null, совместимым с типом компонента массива. Если S — тип объекта, на который ссылается value, а T — тип ссылки компонентов массива, то aastore определяет совместимость присваивания следующим образом:
-
Если S — тип класса, то:
-
Если T — тип класса, то S должен быть тем же классом, что и T, или S должен быть подклассом T;
-
Если T — тип интерфейса, то S должен реализовывать интерфейс T.
-
-
Если S — тип массива SC
[], то есть массив компонентов типа SC, то:-
Если T — тип класса, то T должен быть
Object. -
Если T — тип интерфейса, то T должен быть одним из интерфейсов, реализуемых массивами (JLS §4.10.3).
-
Если T — тип массива TC
[], то есть массив компонентов типа TC, то одно из следующих утверждений должно быть истинным:-
TC и SC — один и тот же примитивный тип.
-
TC и SC — типы ссылок, и тип SC присваивается TC по этим правилам выполнения.
-
-
Исключения во время выполнения
Если arrayref является null, aastore вызывает исключение NullPointerException.
В противном случае, если index выходит за пределы массива, на который ссылается arrayref, инструкция aastore вызывает исключение ArrayIndexOutOfBoundsException.
В противном случае, если arrayref не является null и фактический тип не-null value не совместим с фактическим типом компонентов массива, aastore вызывает исключение ArrayStoreException.
aconst_null
Операция
Помещение null
Формат
aconst_null
Формы
aconst_null = 1 (0x1)
Стек операндов
... →
..., null
Описание
Помещение объекта null reference в стек операндов.
Примечания
Виртуальная машина Java не предписывает конкретное значение для null.
aload
Операция
Загрузка reference из локальной переменной
Формат
aload
index
Формы
aload = 25 (0x19)
Стек операндов
... →
..., objectref
Описание
Значение index — это беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу index должна содержать reference. Объект objectref из локальной переменной по индексу index помещается на стек операндов.
Примечания
Инструкция aload не может быть использована для загрузки значения типа returnAddress из локальной переменной на стек операндов. Эта асимметрия с инструкцией astore (§astore) является умышленной.
Операция aload может использоваться в сочетании с инструкцией wide (§wide) для доступа к локальной переменной, используя двухбайтовый беззнаковый индекс.
aload_<n>
Операция
Загрузка reference из локальной переменной
Формат
aload_<n>
Формы
aload_0 = 42 (0x2a)
aload_1 = 43 (0x2b)
aload_2 = 44 (0x2c)
aload_3 = 45 (0x2d)
Стек операндов
... →
..., objectref
Описание
Значение <n> должно быть индексом в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу <n> должна содержать reference. Объект objectref из локальной переменной по индексу <n> помещается на стек операндов.
Примечания
Инструкция aload_<n> не может быть использована для загрузки значения типа returnAddress из локальной переменной на стек операндов. Эта асимметрия с соответствующей инструкцией astore_<n> (§astore_<n>) является умышленной.
Каждая из инструкций aload_<n> аналогична aload с индексом <n>, за исключением того, что операнд <n> неявный.
anewarray
Операция
Создание нового массива reference
Формат
anewarray
indexbyte1
indexbyte2
Формы
anewarray = 189 (0xbd)
Стек операндов
..., count →
..., arrayref
Описание
Значение count должно быть типа int. Оно извлекается со стека операндов. count представляет количество компонентов создаваемого массива. Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле констант времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула констант времени выполнения по этому индексу должен быть символической ссылкой на тип класса, массива или интерфейса. Указанный тип класса, массива или интерфейса разрешается (§5.4.3.1). Создается новый массив с компонентами этого типа, длиной count, выделенный в куче сборки мусора, и ссылка arrayref на этот новый объект массива помещается на стек операндов. Все компоненты нового массива инициализируются значением по умолчанию для типов reference (§2.4).
Исключения при связывании
При разрешении символической ссылки на тип класса, массива или интерфейса могут быть выброшены любые исключения, описанные в §5.4.3.1.
Исключения времени выполнения
В противном случае, если count меньше нуля, инструкция anewarray генерирует исключение NegativeArraySizeException.
Примечания
Инструкция anewarray используется для создания одномерного массива ссылок на объекты или части многомерного массива.
areturn
Операция
Возврат reference из метода
Формат
areturn
Формы
areturn = 176 (0xb0)
Стек операндов
..., objectref →
[пустой]
Описание
objectref должен быть типа reference и должен ссылаться на объект типа, совместимого с типом, представленным дескриптором возврата (§4.3.3) текущего метода. Если текущий метод является методом synchronized, монитор, захваченный или повторно захваченный при вызове метода, обновляется и, возможно, выходит, как если бы выполнялась инструкция monitorexit (§monitorexit) в текущем потоке. Если исключение не генерируется, objectref извлекается из стека операндов текущей рамки (§2.6) и помещается в стек операндов рамки вызывающего метода. Все остальные значения в стеке операндов текущего метода удаляются.
Затем интерпретатор восстанавливает рамку вызывающего метода и возвращает управление вызывающему методу.
Исключения во время выполнения
Если реализация Java Virtual Machine не выполняет правила структурированной блокировки, описанные в §2.11.10, то если текущий метод является методом synchronized, а текущий поток не является владельцем монитора, захваченного или повторно захваченного при вызове метода, то areturn генерирует исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит инструкцию monitorexit, но не инструкцию monitorenter, для объекта, на котором синхронизирован метод.
В противном случае, если реализация Java Virtual Machine выполняет правила структурированной блокировки, описанные в §2.11.10, и если первое из этих правил нарушается во время вызова текущего метода, то areturn генерирует исключение IllegalMonitorStateException.
arraylength
Операция
Получение длины массива
Формат
arraylength
Формы
arraylength = 190 (0xbe)
Стек операндов
..., arrayref →
..., length
Описание
arrayref должен быть типа reference и должен ссылаться на массив. Он извлекается из стека операндов. Определяется длина length массива, на который он ссылается. Эта длина length помещается в стек операндов как int.
Исключения во время выполнения
Если arrayref является null, инструкция arraylength генерирует исключение NullPointerException.
astore
Операция
Сохранение reference в локальную переменную
Формат
astore
index
Формы
astore = 58 (0x3a)
Стек операндов
..., objectref →
...
Описание
index — это беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей рамки (§2.6). objectref вверху стека операндов должен быть типа returnAddress или типа reference. Он извлекается из стека операндов, и значение локальной переменной по индексу index устанавливается в objectref.
Примечания
Инструкция astore используется с objectref типа returnAddress при реализации фрагмента finally языка программирования Java (§3.13).
Инструкция aload (§aload) не может использоваться для загрузки значения типа returnAddress из локальной переменной в стек операндов. Эта асимметрия с инструкцией astore является намеренной.
Код операции astore может использоваться совместно с инструкцией wide (§wide), чтобы получить доступ к локальной переменной, используя двубайтовый беззнаковый индекс.
astore_<n>
Операция
Сохранение reference в локальной переменной
Формат
astore_<n>
Формы
astore_0 = 75 (0x4b)
astore_1 = 76 (0x4c)
astore_2 = 77 (0x4d)
astore_3 = 78 (0x4e)
Стек операндов
..., objectref →
...
Описание
<n> должно быть индексом в массиве локальных переменных текущей рамки (§2.6). objectref вверху стека операндов должен быть типа returnAddress или типа reference. Он извлекается из стека операндов, и значение локальной переменной в <n> устанавливается в objectref.
Примечания
Инструкции astore_<n> используются с objectref типа returnAddress при реализации положений языка программирования Java (§3.13).
Инструкция aload_<n> (§aload_<n>) не может быть использована для загрузки значения типа returnAddress из локальной переменной в стек операндов. Эта асимметрия с соответствующей инструкцией astore_<n> намеренная.
Каждая из инструкций astore_<n> аналогична инструкции astore с index <n>, за исключением того, что операнд <n> неявный.
athrow
Операция
Выброс исключения или ошибки
Формат
athrow
Формы
athrow = 191 (0xbf)
Стек операндов
..., objectref →
objectref
Описание
objectref должен быть типа reference и должен ссылаться на объект, являющийся экземпляром класса Throwable или подкласса Throwable. Он извлекается из стека операндов. objectref затем выбрасывается, выполняя поиск в текущем методе (§2.6) первого обработчика исключений, соответствующего классу objectref, как задано алгоритмом в §2.10.
Если обработчик исключений, соответствующий objectref, найден, он содержит местоположение кода, предназначенного для обработки этого исключения. Регистр pc сбрасывается до этого местоположения, стек операндов текущей рамки очищается, objectref заново помещается в стек операндов, и выполнение продолжается.
Если соответствующий обработчик исключений не найден в текущей рамке, эта рамка извлекается. Если текущая рамка представляет вызов метода synchronized, монитор, вошедший или повторно вошедший во время вызова метода, выходит, как если бы была выполнена инструкция monitorexit (§monitorexit). Наконец, рамка вызывающего метода, если она существует, восстанавливается, и objectref повторно выбрасывается. Если такой рамки нет, текущий поток завершается.
Исключения во время выполнения
Если objectref null, athrow выбрасывает NullPointerException вместо objectref.
В противном случае, если реализация Java Virtual Machine не применяет правила структурированного блокирования, описанные в §2.11.10, то если метод текущей рамки является методом synchronized, и текущий поток не является владельцем монитора, вошедшего или повторно вошедшего во время вызова метода, athrow выбрасывает IllegalMonitorStateException вместо объекта, ранее подлежащего выбросу. Это может произойти, например, если метод synchronized, прерывающий выполнение, содержит инструкцию monitorexit, но не инструкцию monitorenter, на объекте, на котором синхронизирован метод.
В противном случае, если реализация Java Virtual Machine применяет правила структурированного блокирования, описанные в §2.11.10, и если первое из этих правил нарушено во время вызова текущего метода, то athrow выбрасывает IllegalMonitorStateException вместо объекта, ранее подлежащего выбросу.
Примечания
Диаграмма стека операндов для инструкции athrow может быть вводящей в заблуждение: Если обработчик этого исключения соответствует в текущем методе, инструкция athrow отбрасывает все значения в стеке операндов, а затем помещает выброшенный объект в стек операндов. Однако, если обработчик не найден в текущем методе и исключение выбрасывается выше по цепочке вызова методов, то стек операндов метода (если есть), который обрабатывает исключение, очищается, и objectref помещается в этот пустой стек операндов. Все промежуточные рамки от метода, который сбросил исключение до, но не включая, метод, который обрабатывает исключение, отбрасываются.
baload
Операция
Загрузка из массива типа byte или boolean
Формат
baload
Формы
baload = 51 (0x33)
Стек операндов
..., arrayref, index →
..., value
Описание
arrayref должен быть типа reference и ссылаться на массив, компоненты которого являются типа byte или типа boolean. index должен быть типа int. Оба arrayref и index извлекаются со стека операндов. Значение value компонента массива по индексу index извлекается, расширяется со знаком до значения типа int и помещается на вершину стека операндов.
Исключения во время выполнения
Если arrayref имеет значение null, инструкция baload генерирует исключение NullPointerException.
В противном случае, если index выходит за пределы границ массива, к которому ссылается arrayref, инструкция baload генерирует исключение ArrayIndexOutOfBoundsException.
Примечания
Инструкция baload используется для загрузки значений из массивов byte и boolean. В реализации Oracle's Java Virtual Machine, массивы boolean, то есть массивы типа T_BOOLEAN (§2.2, §newarray), реализованы как массивы 8-битовых значений. Другие реализации могут реализовывать упакованные массивы boolean; инструкция baload таких реализаций должна использоваться для доступа к этим массивам.
bastore
Операция
Сохранение в массив типа byte или boolean
Формат
bastore
Формы
bastore = 84 (0x54)
Стек операндов
..., arrayref, index, value →
...
Описание
arrayref должен быть типа reference и ссылаться на массив, компоненты которого являются типа byte или типа boolean. index и value должны быть типа int. Значения arrayref, index и value извлекаются со стека операндов.
Если arrayref ссылается на массив, компоненты которого являются типа byte, то значение value усекается до типа byte и сохраняется как компонент массива по индексу index.
Если arrayref ссылается на массив, компоненты которого являются типа boolean, то значение value сужается, взяв побитовое И от value и 1; результат сохраняется как компонент массива по индексу index.
Исключения во время выполнения
Если arrayref имеет значение null, инструкция bastore генерирует исключение NullPointerException.
В противном случае, если index выходит за пределы границ массива, к которому ссылается arrayref, инструкция bastore генерирует исключение ArrayIndexOutOfBoundsException.
Примечания
Инструкция bastore используется для сохранения значений в массивы byte и boolean. В реализации Oracle's Java Virtual Machine, массивы boolean, то есть массивы типа T_BOOLEAN (§2.2, §newarray), реализованы как массивы 8-битовых значений. Другие реализации могут реализовывать упакованные массивы boolean; в таких реализациях инструкция bastore должна уметь сохранять значения типа boolean в упакованные массивы boolean, а также значения типа byte в массивы типа byte.
bipush
Операция
Поместить byte
Формат
bipush
byte
Формы
bipush = 16 (0x10)
Стек операндов
... →
..., value
Описание
Непосредственное значение byte расширяется со знаком до значения типа int. Это значение value помещается на стек операндов.
caload
Операция
Загрузка из массива
Формат
caload
Формы
caload = 52 (0x34)
Стек операндов
..., arrayref, index →
..., value
Описание
arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип char. index должен быть типа int. Оба arrayref и index извлекаются из стека операндов. Компонент массива по индексу index извлекается и расширяется до нуля до типа int value. Этот value помещается в стек операндов.
Исключения во время выполнения
Если arrayref является null, caload выбрасывает исключение NullPointerException.
В противном случае, если index не находится в пределах границ массива, на который ссылается arrayref, инструкция caload выбрасывает исключение ArrayIndexOutOfBoundsException.
castore
Операция
Запись в массив
Формат
castore
Формы
castore = 85 (0x55)
Стек операндов
..., arrayref, index, value →
...
Описание
arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип char. index и value должны быть типа int. arrayref, index и value извлекаются из стека операндов. Значение value преобразуется к типу char и сохраняется в качестве компонента массива по индексу index.
Исключения во время выполнения
Если arrayref является null, castore выбрасывает исключение NullPointerException.
В противном случае, если index не находится в пределах границ массива, на который ссылается arrayref, инструкция castore выбрасывает исключение ArrayIndexOutOfBoundsException.
checkcast
Операция
Проверка, является ли объект заданного типа
Формат
checkcast
indexbyte1
indexbyte2
Формы
checkcast = 192 (0xc0)
Стек операндов
..., objectref →
..., objectref
Описание
objectref должен быть типа reference. Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения по данному индексу должен быть символической ссылкой на тип класса, массива или интерфейса.
Если objectref является null, то стек операндов не изменяется.
В противном случае, указанный тип класса, массива или интерфейса разрешается (§5.4.3.1). Если objectref может быть приведён к типу разрешённого класса, массива или интерфейса, стек операндов не изменяется; в противном случае инструкция checkcast генерирует исключение ClassCastException.
Следующие правила используются для определения возможности приведения objectref, который не является null, к разрешённому типу. Если S — тип объекта, на который ссылается objectref, а T — разрешённый тип класса, массива или интерфейса, то checkcast определяет возможность приведения objectref к типу T следующим образом:
-
Если S — тип класса, то:
-
Если T — тип класса, то S должен быть тем же классом, что и T, или S должен быть подклассом T;
-
Если T — тип интерфейса, то S должен реализовывать интерфейс T.
-
-
Если S — тип массива SC
[], то есть массив компонентов типа SC, то:-
Если T — тип класса, то T должен быть
Object. -
Если T — тип интерфейса, то T должен быть одним из интерфейсов, реализуемых массивами (JLS §4.10.3).
-
Если T — тип массива TC
[], то есть массив компонентов типа TC, то одно из следующих утверждений должно быть истинным:-
TC и SC являются одним и тем же примитивным типом.
-
TC и SC являются ссылочными типами, и тип SC может быть приведён к TC путём рекурсивного применения этих правил.
-
-
Исключения при связывании
Во время разрешения символической ссылки на тип класса, массива или интерфейса могут быть сгенерированы любые исключения, описанные в §5.4.3.1.
Исключение времени выполнения
В противном случае, если objectref не может быть приведён к разрешённому классу, массиву или типу интерфейса, инструкция checkcast генерирует исключение ClassCastException.
Примечания
Инструкция checkcast очень похожа на инструкцию instanceof (§instanceof). Они отличаются по обработке null, поведению при неудачном тесте (checkcast генерирует исключение, instanceof помещает результат в стек), и по своему воздействию на стек операндов.
d2f
Операция
Преобразование double в float
Формат
d2f
Формы
d2f = 144 (0x90)
Стек операндов
..., value →
..., result
Описание
value вверху стека операндов должен быть типа double. Он извлекается из стека операндов и преобразуется в float result с помощью политики округления до ближайшего значения (§2.8). result помещается в стек операндов.
Конечное value, слишком маленькое для представления в виде float, преобразуется в ноль с тем же знаком; конечное value, слишком большое для представления в виде float, преобразуется в бесконечность с тем же знаком. double NaN преобразуется в float NaN.
Примечания
Инструкция d2f выполняет сужающее преобразование примитивных типов (JLS §5.1.3). Она может потерять информацию об общем значении value и может также потерять точность.
d2i
Операция
Преобразовать double в int
Формат
d2i
Формы
d2i = 142 (0x8e)
Стек операндов
..., значение →
..., результат
Описание
Значение значение на вершине стека операндов должно быть типа double. Оно извлекается из стека операндов и преобразуется в целочисленное значение результат. Результат помещается в стек операндов:
-
Если значение равно NaN, результат преобразования — целое число 0.
-
В противном случае, если значение не бесконечно, оно округляется до целого значения V с применением правила округления к нулю (§2.8). Если это целое значение V может быть представлено как
int, то результат — значение V типаint. -
В противном случае, либо значение слишком мало (отрицательное значение большой величины или отрицательная бесконечность), и результатом является наименьшее представимое значение типа
int, либо значение слишком велико (положительное значение большой величины или положительная бесконечность), и результатом является наибольшее представимое значение типаint.
Примечания
Инструкция d2i выполняет сужение примитивного преобразования (JLS §5.1.3). Она может потерять информацию о величине значение и может также потерять точность.
d2l
Операция
Преобразовать double в long
Формат
d2l
Формы
d2l = 143 (0x8f)
Стек операндов
..., значение →
..., результат
Описание
Значение значение на вершине стека операндов должно быть типа double. Оно извлекается из стека операндов и преобразуется в целое значение результат. Результат помещается в стек операндов:
-
Если значение равно NaN, результат преобразования — целое число 0.
-
В противном случае, если значение не бесконечно, оно округляется до целого значения V с применением правила округления к нулю (§2.8). Если это целое значение V может быть представлено как
long, то результат — значение V типаlong. -
В противном случае, либо значение слишком мало (отрицательное значение большой величины или отрицательная бесконечность), и результатом является наименьшее представимое значение типа
long, либо значение слишком велико (положительное значение большой величины или положительная бесконечность), и результатом является наибольшее представимое значение типаlong.
Примечания
Инструкция d2l выполняет сужение примитивного преобразования (JLS §5.1.3). Она может потерять информацию о величине значение и может также потерять точность.
dadd
Операция
Сложить double
Формат
dadd
Формы
dadd = 99 (0x63)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа double. Значения извлекаются из стека операндов. Результат результат — значение1 + значение2. Результат помещается в стек операндов.
Результат инструкции dadd определяется правилами арифметики IEEE 754:
-
Если либо значение1, либо значение2 равно NaN, результат — NaN.
-
Сумма двух бесконечностей с разными знаками — NaN.
-
Сумма двух бесконечностей с одинаковыми знаками — бесконечность с таким же знаком.
-
Сумма бесконечности и любого конечного значения равна бесконечности.
-
Сумма двух нулей с разными знаками — положительный ноль.
-
Сумма двух нулей с одинаковыми знаками — ноль с таким же знаком.
-
Сумма нуля и ненулевого конечного значения равна ненулевому значению.
-
Сумма двух ненулевых конечных значений с одинаковой величиной и разными знаками — положительный ноль.
-
В остальных случаях, когда ни один из операндов не является бесконечностью, нулём или NaN, и значения имеют одинаковый знак или разные величины, сумма вычисляется и округляется до ближайшего представимого значения с применением правила округления к ближайшему (§2.8). Если величина слишком велика для представления как
double, то говорят, что произошёл переполнение; результат — бесконечность с соответствующим знаком. Если величина слишком мала для представления какdouble, то говорят, что произошёл недолив; результат — ноль с соответствующим знаком.
Виртуальная машина Java требует поддержки постепенного недолива. Несмотря на то, что переполнение, недолив или потеря точности могут произойти, выполнение инструкции dadd никогда не вызывает исключения выполнения.
daload
Операция
Загрузка значения из массива double
Формат
daload
Формы
daload = 49 (0x31)
Стек операндов
..., arrayref, index →
..., value
Описание
arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип double. index должен быть типа int. И arrayref, и index извлекаются из стека операндов. Значение value компонента массива по индексу index извлекается и помещается в стек операндов.
Исключения во время выполнения
Если arrayref является null, то daload генерирует исключение NullPointerException.
В противном случае, если index выходит за пределы границ массива, указанного arrayref, инструкция daload генерирует исключение ArrayIndexOutOfBoundsException.
dastore
Операция
Сохранение значения в массив double
Формат
dastore
Формы
dastore = 82 (0x52)
Стек операндов
..., arrayref, index, value →
...
Описание
arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип double. index должен быть типа int, а 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) в стек операндов.
ddiv
Деление
Деление double
Формат
ddiv
Формы
ddiv = 111 (0x6f)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба value1 и value2 должны быть типа double. Значения извлекаются из стека операндов. Результат result равен value1 / value2. Результат записывается в стек операндов.
Результат инструкции ddiv подчиняется правилам арифметики IEEE 754:
-
Если value1 или value2 равно NaN, результат равен NaN.
-
Если ни value1, ни value2 не равно NaN, знак результата положителен, если оба значения имеют одинаковый знак, и отрицателен, если значения имеют разные знаки.
-
Деление бесконечности на бесконечность приводит к NaN.
-
Деление бесконечности на конечное значение приводит к бесконечности соответствующего знака, с учетом правила определения знака.
-
Деление конечного значения на бесконечность приводит к нулю соответствующего знака, с учетом правила определения знака.
-
Деление нуля на ноль приводит к NaN; деление нуля на любое другое конечное значение приводит к нулю соответствующего знака, с учетом правила определения знака.
-
Деление ненулевого конечного значения на ноль приводит к бесконечности соответствующего знака, с учетом правила определения знака.
-
В остальных случаях, когда ни один операнд не является бесконечностью, нулём или NaN, частное вычисляется и округляется до ближайшего
doubleиспользуя политику округления до ближайшего (§2.8). Если значение слишком велико для представления в качествеdouble, операция переполняется; результат тогда является бесконечностью соответствующего знака. Если значение слишком мало для представления в качествеdouble, операция подполняется; результат тогда является нулём соответствующего знака.
Java Virtual Machine требует поддержки постепенного подполнения. Несмотря на то, что могут возникнуть переполнение, подполение, деление на ноль или потеря точности, выполнение инструкции ddiv никогда не вызывает исключения времени выполнения.
dload
Операция
Загрузка double из локальной переменной
Формат
dload
index
Формы
dload = 24 (0x18)
Стек операндов
... →
..., value
Описание
index – это беззнаковый байт. И index, и index+1 должны быть индексами в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу index должна содержать double. Значение локальной переменной по индексу index помещается в стек операндов.
Примечания
Инструкция dload может использоваться совместно с инструкцией wide (§wide) для доступа к локальной переменной с помощью двубайтного беззнакового индекса.
dload_<n>
Операция
Загрузка double из локальной переменной
Формат
dload_<n>
Формы
dload_0 = 38 (0x26)
dload_1 = 39 (0x27)
dload_2 = 40 (0x28)
dload_3 = 41 (0x29)
Стек операндов
... →
..., value
Описание
И <n>, и <n>+1 должны быть индексами в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу <n> должна содержать double. Значение локальной переменной по индексу <n> помещается в стек операндов.
Примечания
Каждая из инструкций dload_<n> эквивалентна dload с индексом <n>, за исключением того, что операнд <n> неявный.
dmul
Операция
Умножение double
Формат
dmul
Формы
dmul = 107 (0x6b)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа double. Значения извлекаются из стека операндов. double результат равен значение1 * значение2. Результат помещается в стек операндов.
Результат инструкции dmul регулируется правилами арифметики IEEE 754:
-
Если значение1 или значение2 равно NaN, результат равен NaN.
-
Если ни значение1, ни значение2 не равны NaN, знак результата положительный, если оба значения имеют одинаковый знак, и отрицательный, если знаки различны.
-
Умножение бесконечности на ноль приводит к NaN.
-
Умножение бесконечности на конечное значение приводит к бесконечности соответствующего знака, согласно правилу определения знака.
-
В остальных случаях, когда ни бесконечность, ни NaN не участвуют, произведение вычисляется и округляется до ближайшего представимого значения с использованием политики округления до ближайшего (§2.8). Если значение слишком большое для представления как
double, операция переполняется; результат — бесконечность соответствующего знака. Если значение слишком мало для представления какdouble, операция переполняется; результат — ноль соответствующего знака.
Виртуальная машина Java требует поддержки постепенного переполнения. Несмотря на то, что может произойти переполнение, недополнение или потеря точности, выполнение инструкции dmul никогда не вызывает исключение времени выполнения.
dneg
Операция
Изменение знака double
Формат
dneg
Формы
dneg = 119 (0x77)
Стек операндов
..., значение →
..., результат
Описание
Значение должно быть типа double. Оно извлекается из стека операндов. 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)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа double. Значения извлекаются из стека операндов. double результат вычисляется и помещается в стек операндов.
Результат инструкции drem не совпадает с результатом операции нахождения остатка, определенной в IEEE 754, из-за выбора политики округления в виртуальной машине Java (§2.8). Операция нахождения остатка IEEE 754 вычисляет остаток от округленного деления, а не от усеченного, и поэтому ее поведение не аналогично поведению обычного целочисленного оператора остатка. Вместо этого, виртуальная машина Java определяет drem так, чтобы он вел себя аналогично целочисленным операторам остатка irem и lrem, с неявным делением с политикой округления к нулю; это можно сравнить с функцией C-библиотеки fmod.
Результат инструкции drem регулируется следующими правилами, которые соответствуют арифметике IEEE 754, за исключением способа вычисления неявного деления:
-
Если значение1 или значение2 равно NaN, результат равен NaN.
-
Если ни значение1, ни значение2 не равны NaN, знак результата равен знаку делимого.
-
Если делимое — бесконечность или делитель — ноль, или оба, результат равен NaN.
-
Если делимое конечно, а делитель — бесконечность, результат равен делимому.
-
Если делимое равно нулю, а делитель конечен, результат равен делимому.
-
В оставшихся случаях, когда ни один операнд не является бесконечностью, нулем или NaN, остаток с плавающей точкой результат от делимого значение1 и делителя значение2 определяется математическим соотношением результат = значение1 - (значение2 * q), где q — целое число, которое отрицательно только если значение1 / значение2 отрицательно, и положительно только если значение1 / значение2 положительно, и его абсолютное значение максимально возможно без превышения абсолютного значения истинного математического частного значение1 и значение2.
Несмотря на то, что деление на ноль может произойти, вычисление инструкции drem никогда не вызывает исключения времени выполнения. Переполнение, недополнение или потеря точности невозможны.
Примечания
Операцию нахождения остатка IEEE 754 можно вычислить с помощью библиотечной функции Math.IEEEremainder или StrictMath.IEEEremainder.
dreturn
Операция
Возврат double из метода
Формат
dreturn
Формы
dreturn = 175 (0xaf)
Стек операндов
..., value →
[пусто]
Описание
Текущий метод должен иметь тип возвращаемого значения double. value должен быть типа double. Если текущий метод является методом synchronized, то монитор, вошедший или повторно вошедший при вызове метода, обновляется и, возможно, выходит, как если бы он был выполнен инструкцией monitorexit (§monitorexit) в текущем потоке. Если исключение не возникает, value извлекается из стека операндов текущей рамки (§2.6) и помещается в стек операндов рамки вызывающего метода. Любые другие значения в стеке операндов текущего метода удаляются.
Затем интерпретатор возвращает управление вызывающему методу, восстанавливая рамку вызывающего метода.
Исключения во время выполнения
Если реализация Java Virtual Machine не соблюдает правила структурированных блокировок, описанные в §2.11.10, то если текущий метод является методом synchronized, а текущий поток не является владельцем монитора, вошедшего или повторно вошедшего при вызове метода, dreturn генерирует исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит инструкцию monitorexit, но не инструкцию monitorenter, для объекта, на котором синхронизирован метод.
В противном случае, если реализация Java Virtual Machine соблюдает правила структурированных блокировок, описанные в §2.11.10, и если первое из этих правил нарушается во время вызова текущего метода, то dreturn генерирует исключение IllegalMonitorStateException.
dstore
Операция
Сохранение double в локальной переменной
Формат
dstore
index
Формы
dstore = 57 (0x39)
Стек операндов
..., value →
...
Описание
index — беззнаковый байт. И index, и index+1 должны быть индексами в массив локальных переменных текущей рамки (§2.6). value в верхней части стека операндов должен быть типа double. Он извлекается из стека операндов. Локальные переменные по индексам index и index+1 устанавливаются в значение value.
Примечания
Инструкция dstore может использоваться совместно с инструкцией wide (§wide) для доступа к локальной переменной с использованием двухбайтового беззнакового индекса.
dstore_<n>
Операция
Сохранение double в локальной переменной
Формат
dstore_<n>
Формы
dstore_0 = 71 (0x47)
dstore_1 = 72 (0x48)
dstore_2 = 73 (0x49)
dstore_3 = 74 (0x4a)
Стек операндов
..., value →
...
Описание
И <n>, и <n>+1 должны быть индексами в массив локальных переменных текущей рамки (§2.6). value в верхней части стека операндов должен быть типа double. Он извлекается из стека операндов. Локальные переменные по индексам <n> и <n>+1 устанавливаются в значение value.
Примечания
Каждая из инструкций dstore_<n> эквивалентна инструкции dstore с индексом <n>, за исключением того, что операнд <n> неявный.
dsub
Операция
Вычитание double
Формат
dsub
Формы
dsub = 103 (0x67)
Стек операндов
..., value1, value2 →
..., result
Описание
value1 и value2 должны быть типа double. Значения извлекаются из стека операндов. Результат result — value1 - value2. Результат помещается в стек операндов.
Для вычитания double, всегда верно, что a-b производит тот же результат, что и a+(-b). Однако для инструкции dsub вычитание из нуля не равно отрицанию, потому что если x равно +0.0, то 0.0-x равно +0.0, но -x равно -0.0.
Java Virtual Machine требует поддержки постепенного недолива. Несмотря на то, что может произойти переполнение, недолив или потеря точности, выполнение инструкции dsub никогда не генерирует исключение во время выполнения.
dup
Операция
Дублирует верхнее значение стека операндов
Формат
dup
Формы
dup = 89 (0x59)
Стек операндов
..., value →
..., value, value
Описание
Дублирует верхнее значение в стеке операндов и помещает дублированное значение в стек операндов.
Инструкцию dup нельзя использовать, если value не является значением вычислительного типа категории 1 (§2.11.1).
dup_x1
Операция
Дублирует верхнее значение стека операндов и вставляет два значения вниз
Формат
dup_x1
Формы
dup_x1 = 90 (0x5a)
Стек операндов
..., value2, value1 →
..., value1, value2, value1
Описание
Дублирует верхнее значение в стеке операндов и вставляет дублированное значение на два значения вниз в стеке операндов.
Инструкцию dup_x1 нельзя использовать, если оба value1 и value2 являются значениями вычислительного типа категории 1 (§2.11.1).
dup_x2
Операция
Дублирует верхнее значение стека операндов и вставляет два или три значения вниз
Формат
dup_x2
Формы
dup_x2 = 91 (0x5b)
Стек операндов
Форма 1:
..., value3, value2, value1 →
..., value1, value3, value2, value1
где value1, value2 и value3 — все значения вычислительного типа категории 1 (§2.11.1).
Форма 2:
..., value2, value1 →
..., value1, value2, value1
где value1 — значение вычислительного типа категории 1, а value2 — значение вычислительного типа категории 2 (§2.11.1).
Описание
Дублирует верхнее значение в стеке операндов и вставляет дублированное значение на два или три значения вниз в стеке операндов.
dup2
Операция
Дублирует верхнее одно или два значения стека операндов
Формат
dup2
Формы
dup2 = 92 (0x5c)
Стек операндов
Форма 1:
..., value2, value1 →
..., value2, value1, value2, value1
где оба value1 и value2 являются значениями вычислительного типа категории 1 (§2.11.1).
Форма 2:
..., value →
..., value, value
где value — значение вычислительного типа категории 2 (§2.11.1).
Описание
Дублирует одно или два верхних значения в стеке операндов и помещает дублированное значение или значения обратно в стек операндов в исходном порядке.
dup2_x1
Операция
Дублирует верхнее одно или два значения стека операндов и вставляет два или три значения вниз
Формат
dup2_x1
Формы
dup2_x1 = 93 (0x5d)
Стек операндов
Форма 1:
..., value3, value2, value1 →
..., value2, value1, value3, value2, value1
где value1, value2 и value3 — все значения вычислительного типа категории 1 (§2.11.1).
Форма 2:
..., value2, value1 →
..., value1, value2, value1
где value1 — значение вычислительного типа категории 2, а value2 — значение вычислительного типа категории 1 (§2.11.1).
Описание
Дублирует одно или два верхних значения в стеке операндов и вставляет дублированные значения в исходном порядке на одно значение ниже исходного значения или значений в стеке операндов.
dup2_x2
Операция
Дублирует верхнее одно или два значения стека операндов и вставляет дублированные значения на два, три или четыре уровня вниз
Формат
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, результат преобразования —
int0. -
В противном случае, если 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, результат преобразования равен
long0. -
В противном случае, если значение не является бесконечностью, оно округляется до целого значения V с использованием правила округления до нуля (§2.8). Если это целое значение V может быть представлено как
long, то результат — это значениеlongV. -
В противном случае, либо значение слишком мало (отрицательное значение большой величины или отрицательная бесконечность), и результат — наименьшее представимое значение типа
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 требует поддержки постепенного переполнения. Несмотря на то, что может произойти переполнение, недополнение или потеря точности, выполнение инструкции 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 извлекаются из стека операндов. Значение float value сохраняется в качестве компонента массива с индексом index.
Исключения во время выполнения
Если arrayref является null, fastore генерирует исключение NullPointerException.
В противном случае, если index не находится в границах массива, на который ссылается arrayref, инструкция fastore генерирует исключение ArrayIndexOutOfBoundsException.
fcmp<op>
Операция
Сравнение float
Формат
fcmp<op>
Формы
fcmpg = 150 (0x96)
fcmpl = 149 (0x95)
Стек операндов
..., value1, value2 →
..., result
Описание
И value1, и value2 должны быть типа float. Значения извлекаются из стека операндов, и выполняется сравнение с плавающей точкой:
-
Если value1 больше value2, на стек операндов помещается значение 1.
-
Если value1 равно value2, на стек операндов помещается значение 0.
-
Если value1 меньше value2, на стек операндов помещается значение -1.
-
В противном случае, по крайней мере одно из value1 или value2 - NaN. Инструкция fcmpg помещает на стек операндов значение 1, а fcmpl - значение -1.
Сравнение с плавающей точкой выполняется в соответствии со стандартом IEEE 754. Все значения, кроме NaN, упорядочены, при этом отрицательная бесконечность меньше всех конечных значений, а положительная бесконечность больше всех конечных значений. Положительный и отрицательный нуль считаются равными.
Примечания
Инструкции fcmpg и fcmpl различаются только обработкой сравнения, включающего NaN. NaN неупорядочен, поэтому любое сравнение с участием NaN не выполняется, если хотя бы один из операндов является NaN. Наличие как fcmpg, так и fcmpl позволяет выполнить любое сравнение, которое поместит на стек операндов одинаковое 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)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа float. Значения извлекаются из стека операндов. float результат равен значение1 / значение2. Результат помещается в стек операндов.
Результат инструкции fdiv регулируется правилами арифметики IEEE 754:
-
Если значение1 или значение2 равно NaN, результат равен NaN.
-
Если ни значение1, ни значение2 не равны NaN, знак результата положительный, если оба значения имеют одинаковый знак, и отрицательный, если знаки отличаются.
-
Деление бесконечности на бесконечность приводит к NaN.
-
Деление бесконечности на конечное значение приводит к бесконечности соответствующего знака, согласно правилу.
-
Деление конечного значения на бесконечность приводит к знаку нуля, согласно правилу.
-
Деление нуля на ноль приводит к NaN; деление нуля на любое другое конечное значение приводит к знаку нуля, согласно правилу.
-
Деление ненулевого конечного значения на ноль приводит к бесконечности соответствующего знака, согласно правилу.
-
В оставшихся случаях, когда ни один операнд не является бесконечностью, нулём или NaN, частное вычисляется и округляется к ближайшему
floatиспользуя политику округления до ближайшего значения (§2.8). Если величина слишком велика для представления в видеfloat, то операция переполняет; результат тогда является бесконечностью с соответствующим знаком. Если величина слишком мала для представления в видеfloat, операция переполняет; результат тогда равен нулю с соответствующим знаком.
Машина Java Virtual требует поддержки постепенного переполнения. Несмотря на то, что может произойти переполнение, недополнение, деление на ноль или потеря точности, выполнение инструкции fdiv никогда не вызывает исключение времени выполнения.
fload
Операция
Загрузка float из локальной переменной
Формат
fload
индекс
Формы
fload = 23 (0x17)
Стек операндов
... →
..., значение
Описание
Индекс — это беззнаковый байт, который должен быть индексом в массив локальных переменных текущей фрейма (§2.6). Локальная переменная по индексу должна содержать float. Значение локальной переменной по индексу помещается на стек операндов.
Примечания
Инструкция 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)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа float. Значения извлекаются из стека операндов. Результат результат равен значение1 * значение2. Результат помещается в стек операндов.
Результат инструкции fmul регулируется правилами арифметики IEEE 754:
-
Если значение1 или значение2 равно NaN, результат равен NaN.
-
Если ни значение1, ни значение2 не равно NaN, знак результата положителен, если оба значения имеют одинаковый знак, и отрицателен, если значения имеют разные знаки.
-
Умножение бесконечности на ноль приводит к NaN.
-
Умножение бесконечности на конечное значение приводит к знаковому значению бесконечности, согласно правилу знака.
-
В остальных случаях, когда не участвует бесконечность или NaN, произведение вычисляется и округляется до ближайшего представимого значения с использованием правила округления до ближайшего (§2.8). Если модуль слишком велик, чтобы быть представленным как
float, операция переполняется; результат — бесконечность соответствующего знака. Если модуль слишком мал, чтобы быть представлен какfloat, операция переполняется; результат — ноль соответствующего знака.
Машина Java Virtual требует поддержки постепенного переполнения. Несмотря на то, что может произойти переполнение, недополнение или потеря точности, выполнение инструкции fmul никогда не вызывает исключение времени выполнения.
fneg
Операция
Изменение знака float
Формат
fneg
Формы
fneg = 118 (0x76)
Стек операндов
..., значение →
..., результат
Описание
Значение должно быть типа float. Оно извлекается из стека операндов. Результат результат — арифметическое отрицание значения. Результат помещается в стек операндов.
Для значений float отрицание не равно вычитанию из нуля. Если x равен +0.0, то 0.0-x равен +0.0, но -x равен -0.0. Унарный минус просто инвертирует знак float.
Особые случаи:
-
Если операнд равен NaN, результат равен NaN (NaN не имеет знака).
Java Virtual Machine не приняло более строгое требование из версии IEEE 754 Standard 2019, что отрицание инвертирует бит знака для всех входов, включая NaN.
-
Если операнд — бесконечность, результат — бесконечность противоположного знака.
-
Если операнд — ноль, результат — ноль противоположного знака.
frem
Операция
Остаток float
Формат
frem
Формы
frem = 114 (0x72)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа float. Значения извлекаются из стека операндов. Результат результат вычисляется и помещается в стек операндов.
Результат инструкции frem не совпадает с результатом операции остатка, определённой в IEEE 754, из-за выбора политики округления в Java Virtual Machine (§2.8). Операция остатка IEEE 754 вычисляет остаток от округления деления, а не от усечения, и поэтому её поведение не аналогично обычному оператору остатка целых чисел. Вместо этого Java Virtual Machine определяет frem как аналогичную инструкциям остатка для целых чисел irem и lrem, с подразумеваемым делением с округлением к нулю; это можно сравнить с функцией C-библиотеки fmod.
Результат инструкции frem регулируется следующими правилами, которые соответствуют арифметике IEEE 754 за исключением того, как вычисляется подразумеваемое деление:
-
Если значение1 или значение2 равно NaN, результат равен NaN.
-
Если ни значение1, ни значение2 не равно NaN, знак результата равен знаку делимого.
-
Если делимое — бесконечность или делитель — ноль, или оба, результат равен NaN.
-
Если делимое — конечное, а делитель — бесконечность, результат равен делимому.
-
Если делимое — ноль, а делитель — конечное, результат равен делимому.
-
В остальных случаях, когда ни один из операндов не является бесконечностью, нулём или NaN, остаток с плавающей запятой результат от делимого значение1 и делителя значение2 определяется математическим соотношением результат = значение1 - (значение2 * q), где q — целое число, отрицательное только тогда, когда значение1 / значение2 отрицательно, и положительное только тогда, когда значение1 / значение2 положительно, и его модуль максимально возможен, не превышая модуля истинного математического частного значение1 и значение2.
Несмотря на то, что может произойти деление на ноль, вычисление инструкции frem никогда не вызывает исключения времени выполнения. Переполнение, недополнение или потеря точности невозможны.
Примечания
Операцию остатка IEEE 754 можно вычислить с помощью библиотечной функции Math.IEEEremainder или StrictMath.IEEEremainder.
freturn
Операция
Возврат float из метода
Формат
freturn
Формы
freturn = 174 (0xae)
Стек операндов
..., value →
[пусто]
Описание
Текущий метод должен иметь тип возвращаемого значения float. value должен быть типа float. Если текущий метод является методом synchronized, монитор, вошедший или повторно вошедший при вызове метода, обновляется и, возможно, выходит, как если бы выполнялась инструкция monitorexit (§monitorexit) в текущем потоке. Если исключение не выбрасывается, value извлекается из стека операндов текущей рамки (§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
index
Формы
fstore = 56 (0x38)
Стек операндов
..., value →
...
Описание
index — это беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей рамки (§2.6). Значение value на вершине стека операндов должно быть типа float. Оно извлекается из стека операндов, и значение локальной переменной в позиции index устанавливается в value.
Примечания
Инструкция fstore может использоваться совместно с инструкцией wide (§wide) для доступа к локальной переменной с помощью двубайтового беззнакового индекса.
fstore_<n>
Операция
Сохранение float в локальную переменную
Формат
fstore_<n>
Формы
fstore_0 = 67 (0x43)
fstore_1 = 68 (0x44)
fstore_2 = 69 (0x45)
fstore_3 = 70 (0x46)
Стек операндов
..., value →
...
Описание
<n> должно быть индексом в массиве локальных переменных текущей рамки (§2.6). Значение value на вершине стека операндов должно быть типа float. Оно извлекается из стека операндов, и значение локальной переменной в позиции <n> устанавливается в value.
Примечания
Каждая из инструкций fstore_<n> эквивалентна инструкции fstore с индексом <n>, за исключением того, что операнд <n> неявный.
fsub
Операция
Вычитание float
Формат
fsub
Формы
fsub = 102 (0x66)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба value1 и value2 должны быть типа float. Значения извлекаются из стека операндов. Результат result — это value1 - value2. Результат помещается в стек операндов.
Для вычитания 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).
В противном случае, если разрешенное поле не является полем (класса) static или полем интерфейса, getstatic выбрасывает исключение IncompatibleClassChangeError.
Исключение во время выполнения
В противном случае, если выполнение этой инструкции getstatic вызывает инициализацию ссылаемого класса или интерфейса, getstatic может выбросить исключение Error, как подробно описано в §5.5.
goto
Операция
Безусловный переход
Формат
goto
branchbyte1
branchbyte2
Формы
goto = 167 (0xa7)
Стек операндов
Без изменений
Описание
Беззнаковые байты branchbyte1 и branchbyte2 используются для построения знакового 16-битного смещения (branchoffset), где branchoffset равен (branchbyte1 << 8) | branchbyte2. Выполнение продолжается в смещении от адреса операционного кода данной инструкции goto. Адрес назначения должен соответствовать операционному коду инструкции внутри метода, содержащего эту инструкцию goto.
goto_w
Операция
Безусловный переход (широкий индекс)
Формат
goto_w
branchbyte1
branchbyte2
branchbyte3
branchbyte4
Формы
goto_w = 200 (0xc8)
Операционный стек
Без изменений
Описание
Беззнаковые байты branchbyte1, branchbyte2, branchbyte3 и branchbyte4 используются для построения 32-битного знакового смещения branchoffset, где branchoffset это (branchbyte1 << 24) | (branchbyte2 << 16) | (branchbyte3 << 8) | branchbyte4. Выполнение продолжается по смещению от адреса операции данной инструкции goto_w. Адрес назначения должен быть адресом операции инструкции внутри метода, содержащего данную инструкцию goto_w.
Примечания
Несмотря на то, что инструкция goto_w использует 4-байтовое смещение ветвления, другие факторы ограничивают размер метода до 65535 байтов (§4.11). Это ограничение может быть увеличено в будущих версиях Java Virtual Machine.
i2b
Операция
Преобразование int в byte
Формат
i2b
Формы
i2b = 145 (0x91)
Операционный стек
..., value →
..., result
Описание
Значение value на вершине операционного стека должно быть типа int. Оно извлекается из операционного стека, усекается до byte, а затем расширяется со знаком до int result. Значение result помещается на операционный стек.
Примечания
Инструкция i2b выполняет сужающее преобразование примитивных типов (JLS §5.1.3). Она может потерять информацию о величине value. Знак result может также отличаться от знака value.
i2c
Операция
Преобразование int в char
Формат
i2c
Формы
i2c = 146 (0x92)
Операционный стек
..., value →
..., result
Описание
Значение value на вершине операционного стека должно быть типа int. Оно извлекается из операционного стека, усекается до char, а затем расширяется без знака до int result. Значение result помещается на операционный стек.
Примечания
Инструкция i2c выполняет сужающее преобразование примитивных типов (JLS §5.1.3). Она может потерять информацию о величине value. Значение result (которое всегда положительно) может также отличаться от знака value.
i2d
Операция
Преобразование int в double
Формат
i2d
Формы
i2d = 135 (0x87)
Операционный стек
..., value →
..., result
Описание
Значение value на вершине операционного стека должно быть типа int. Оно извлекается из операционного стека и преобразуется в double result. Значение result помещается на операционный стек.
Примечания
Инструкция i2d выполняет расширяющее преобразование примитивных типов (JLS §5.1.2). Поскольку все значения типа int точно представляются типом double, преобразование точное.
i2f
Операция
Преобразование int в float
Формат
i2f
Формы
i2f = 134 (0x86)
Операционный стек
..., value →
..., result
Описание
Значение value на вершине операционного стека должно быть типа int. Оно извлекается из операционного стека и преобразуется в float result с использованием правила округления до ближайшего значения (§2.8). Значение result помещается на операционный стек.
Примечания
Инструкция i2f выполняет расширяющее преобразование примитивных типов (JLS §5.1.2), но может привести к потере точности, так как значения типа float имеют только 24 бита мантиссы.
i2l
Операция
Преобразовать int в long
Формат
i2l
Формы
i2l = 133 (0x85)
Стек операндов
..., значение →
..., результат
Описание
Значение значение на вершине стека операндов должно быть типа int. Оно извлекается из стека операндов и расширяется со знаком до long результат. Результат помещается на стек операндов.
Примечания
Инструкция i2l выполняет расширяющее преобразование примитивных типов (JLS §5.1.2). Поскольку все значения типа int точно представимы типом long, преобразование является точным.
i2s
Операция
Преобразовать int в short
Формат
i2s
Формы
i2s = 147 (0x93)
Стек операндов
..., значение →
..., результат
Описание
Значение значение на вершине стека операндов должно быть типа int. Оно извлекается из стека операндов, усекается до short, затем расширяется со знаком до int результат. Результат помещается на стек операндов.
Примечания
Инструкция i2s выполняет сужающее преобразование примитивных типов (JLS §5.1.3). При этом может быть потеряна информация о величине значение. Результат также может иметь другой знак, чем значение.
iadd
Операция
Сложить int
Формат
iadd
Формы
iadd = 96 (0x60)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа int. Значения извлекаются из стека операндов. Результат результат равен значение1 + значение2. Результат помещается на стек операндов.
Результат — это 32 младших бита истинного математического результата в достаточно широком формате дополнительного кода, представленного как значение типа int. В случае переполнения знак результата может не совпадать со знаком математической суммы двух значений.
Несмотря на то, что переполнение возможно, выполнение инструкции iadd никогда не вызывает исключение времени выполнения.
iaload
Операция
Загрузка int из массива
Формат
iaload
Формы
iaload = 46 (0x2e)
Стек операндов
..., ссылка_на_массив, индекс →
..., значение
Описание
ссылка_на_массив должна быть типа reference и должна ссылаться на массив, компоненты которого имеют тип int. Индекс должен быть типа int. Оба ссылка_на_массив и индекс извлекаются из стека операндов. Полученное int значение компонента массива по индексу извлекается и помещается на стек операндов.
Исключения времени выполнения
Если ссылка_на_массив является null, iaload выбрасывает NullPointerException.
В противном случае, если индекс не находится в пределах массива, на который ссылается ссылка_на_массив, инструкция iaload выбрасывает ArrayIndexOutOfBoundsException.
iand
Операция
Логическое И int
Формат
iand
Формы
iand = 126 (0x7e)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа int. Они извлекаются из стека операндов. Вычисляется 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>
Описание
Поместить константу <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, то происходит переполнение, и результат равен делимому. Несмотря на переполнение, в этом случае исключение не генерируется.
Исключение во время выполнения
Если значение делителя в делении int равно 0, idiv генерирует исключение ArithmeticException.
if_acmp<cond>
Операция
Разветвление, если reference сравнение успешно
Формат
if_acmp<cond>
branchbyte1
branchbyte2
Формы
if_acmpeq = 165 (0xa5)
if_acmpne = 166 (0xa6)
Стек операндов
..., value1, value2 →
...
Описание
Оба value1 и value2 должны быть типа reference. Они оба извлекаются из стека операндов и сравниваются. Результаты сравнения следующие:
-
if_acmpeq успешно, если и только если value1 = value2
-
if_acmpne успешно, если и только если value1 ≠ value2
Если сравнение успешно, незначащие branchbyte1 и branchbyte2 используются для построения знакового 16-битного смещения, где смещение вычисляется как (branchbyte1 << 8) | branchbyte2. Выполнение затем продолжается по этому смещению от адреса кода этой инструкции if_acmp<cond>. Целевой адрес должен быть адресом кода инструкции внутри метода, содержащего эту инструкцию if_acmp<cond>.
В противном случае, если сравнение не выполнено, выполнение продолжается по адресу инструкции, следующей за этой инструкцией if_acmp<cond>.
if_icmp<cond>
Операция
Разветвление, если int сравнение успешно
Формат
if_icmp<cond>
branchbyte1
branchbyte2
Формы
if_icmpeq = 159 (0x9f)
if_icmpne = 160 (0xa0)
if_icmplt = 161 (0xa1)
if_icmpge = 162 (0xa2)
if_icmpgt = 163 (0xa3)
if_icmple = 164 (0xa4)
Стек операндов
..., value1, value2 →
...
Описание
Оба value1 и value2 должны быть типа int. Они оба извлекаются из стека операндов и сравниваются. Все сравнения являются знаковыми. Результаты сравнения следующие:
-
if_icmpeq успешно, если и только если value1 = value2
-
if_icmpne успешно, если и только если value1 ≠ value2
-
if_icmplt успешно, если и только если value1 < value2
-
if_icmple успешно, если и только если value1 ≤ value2
-
if_icmpgt успешно, если и только если value1 > value2
-
if_icmpge успешно, если и только если value1 ≥ value2
Если сравнение успешно, незначащие branchbyte1 и branchbyte2 используются для построения знакового 16-битного смещения, где смещение вычисляется как (branchbyte1 << 8) | branchbyte2. Выполнение затем продолжается по этому смещению от адреса кода этой инструкции if_icmp<cond>. Целевой адрес должен быть адресом кода инструкции внутри метода, содержащего эту инструкцию if_icmp<cond>.
В противном случае, выполнение продолжается по адресу инструкции, следующей за этой инструкцией if_icmp<cond>.
if<cond>
Операция
Ветвление, если int сравнение с нулём успешно
Формат
if<cond>
branchbyte1
branchbyte2
Формы
ifeq = 153 (0x99)
ifne = 154 (0x9a)
iflt = 155 (0x9b)
ifge = 156 (0x9c)
ifgt = 157 (0x9d)
ifle = 158 (0x9e)
Стек операндов
..., значение →
...
Описание
Значение должно быть типа int. Оно извлекается из стека операндов и сравнивается с нулём. Все сравнения — со знаком. Результаты сравнений следующие:
-
ifeq успешно, если и только если значение = 0
-
ifne успешно, если и только если значение ≠ 0
-
iflt успешно, если и только если значение < 0
-
ifle успешно, если и только если значение ≤ 0
-
ifgt успешно, если и только если значение > 0
-
ifge успешно, если и только если значение ≥ 0
Если сравнение успешно, неподписанные branchbyte1 и branchbyte2 используются для построения 16-битного смещения со знаком, где смещение вычисляется как (branchbyte1 << 8) | branchbyte2. Выполнение затем продолжается по смещению от адреса кода этой инструкции if<cond>. Целевой адрес должен быть адресом кода инструкции внутри метода, содержащего эту инструкцию if<cond>.
В противном случае выполнение продолжается по адресу инструкции, следующей за этой инструкцией if<cond>.
ifnonnull
Операция
Ветвление, если reference не null
Формат
ifnonnull
branchbyte1
branchbyte2
Формы
ifnonnull = 199 (0xc7)
Стек операндов
..., значение →
...
Описание
Значение должно быть типа reference. Оно извлекается из стека операндов. Если значение не null, неподписанные branchbyte1 и branchbyte2 используются для построения 16-битного смещения со знаком, где смещение вычисляется как (branchbyte1 << 8) | branchbyte2. Выполнение затем продолжается по смещению от адреса кода этой инструкции ifnonnull. Целевой адрес должен быть адресом кода инструкции внутри метода, содержащего эту инструкцию ifnonnull.
В противном случае выполнение продолжается по адресу инструкции, следующей за этой инструкцией ifnonnull.
ifnull
Операция
Ветвление, если reference равен null
Формат
ifnull
branchbyte1
branchbyte2
Формы
ifnull = 198 (0xc6)
Стек операндов
..., значение →
...
Описание
Значение должно быть типа reference. Оно извлекается из стека операндов. Если значение равно 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
Операция
Загрузка значения из локальной переменной
Формат
iload
index
Формы
iload = 21 (0x15)
Стек операндов
... →
..., значение
Описание
Значение index — это беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу index должна содержать целое значение. Значение локальной переменной по индексу index помещается на стек операндов.
Примечания
Код операции iload может использоваться совместно с инструкцией wide (§wide) для доступа к локальной переменной с помощью двухбайтового беззнакового индекса.
iload_<n>
Операция
Загрузка значения из локальной переменной
Формат
iload_<n>
Формы
iload_0 = 26 (0x1a)
iload_1 = 27 (0x1b)
iload_2 = 28 (0x1c)
iload_3 = 29 (0x1d)
Стек операндов
... →
..., значение
Описание
Значение <n> должно быть индексом в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу <n> должна содержать целое значение. Значение локальной переменной по индексу <n> помещается на стек операндов.
Примечания
Каждая из инструкций iload_<n> идентична iload с индексом <n>, за исключением того, что операнд <n> неявный.
imul
Операция
Умножение целых чисел
Формат
imul
Формы
imul = 104 (0x68)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть целыми числами. Значения извлекаются из стека операндов. Результат результат — это значение1 * значение2. Результат помещается на стек операндов.
Результат — это 32 младших бита истинного математического результата в достаточном формате со знаком дополнения до двух, представленного как значение типа целое число. Если происходит переполнение, то знак результата может не совпадать со знаком математического умножения двух значений.
Несмотря на то, что может произойти переполнение, выполнение инструкции imul никогда не вызывает исключения во время выполнения.
ineg
Операция
Изменение знака целого числа
Формат
ineg
Формы
ineg = 116 (0x74)
Стек операндов
..., значение →
..., результат
Описание
Значение значение должно быть целым числом. Оно извлекается из стека операндов. Результат результат — это арифметическое отрицание значение, -значение. Результат помещается на стек операндов.
Для целых значений представление с дополнением до двух одинаково, а диапазон значений с дополнением до двух несимметричен, поэтому отрицание максимального отрицательного целого числа приводит к тому же максимальному отрицательному числу. Несмотря на то, что переполнение произошло, исключение не генерируется.
Для всех целых значений необходимо рассматривать соответствующие требования.
instanceof
Операция
Определить, является ли объект заданного типа
Формат
instanceof
indexbyte1
indexbyte2
Формы
instanceof = 193 (0xc1)
Стек операндов
..., objectref →
..., result
Описание
Объект objectref, который должен быть типа reference, извлекается из стека операндов. Беззнаковые значения indexbyte1 и indexbyte2 используются для построения индекса в пуле постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения по этому индексу должен быть символической ссылкой на класс, массив или тип интерфейса.
Если objectref равен null, инструкция instanceof помещает в стек операндов значение результата 0 как int.
В противном случае, заданный класс, массив или тип интерфейса разрешаются (§5.4.3.1). Если objectref является экземпляром разрешенного класса или типа массива, или реализует разрешенный интерфейс, инструкция instanceof помещает в стек операндов значение результата 1 как int; в противном случае, она помещает значение результата 0.
Для определения, является ли objectref, который не равен null, экземпляром разрешенного типа, используются следующие правила. Если S — тип объекта, на который ссылается objectref, а T — разрешенный класс, массив или тип интерфейса, тогда instanceof определяет, является ли objectref экземпляром T следующим образом:
-
Если S — тип класса, то:
-
Если T — тип класса, то S должен быть таким же классом, как T, или S должен быть подклассом T;
-
Если T — тип интерфейса, то S должен реализовывать интерфейс T.
-
-
Если S — тип массива SC
[], то есть массив компонентов типа SC, то:-
Если T — тип класса, то T должен быть
Object. -
Если T — тип интерфейса, то T должен быть одним из интерфейсов, реализуемых массивами (JLS §4.10.3).
-
Если T — тип массива TC
[], то есть массив компонентов типа TC, то одно из следующих условий должно выполняться:-
TC и SC — тот же примитивный тип.
-
TC и SC — ссылочные типы, и тип SC может быть преобразован к типу TC по этим правилам времени выполнения.
-
-
Исключения при установлении связи
Во время разрешения символической ссылки на класс, массив или тип интерфейса могут быть выброшены любые исключения, описанные в §5.4.3.1.
Примечания
Инструкция instanceof очень похожа на инструкцию checkcast (§checkcast). Она отличается обработкой null, своим поведением при неудачном тесте (checkcast генерирует исключение, instanceof помещает код результата) и своим влиянием на стек операндов.
invokedynamic
Операция
Вызов динамически вычисляемого места вызова
Формат
invokedynamic
indexbyte1
indexbyte2
0
0
Формы
invokedynamic = 186 (0xba)
Стек операндов
..., [arg1, [arg2 ...]] →
...
Описание
Сначала неотрицательные значения indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на динамически вычисляемое место вызова (§5.1). Значения третьего и четвёртого байтов операндов всегда должны быть нулевыми.
Символическая ссылка разрешается (§5.4.3.6) для данной конкретной инструкции invokedynamic для получения reference к экземпляру java.lang.invoke.CallSite. Экземпляр java.lang.invoke.CallSite считается "связанным" с этой конкретной инструкцией invokedynamic.
Экземпляр java.lang.invoke.CallSite указывает на обработчик метода-цели. Значения аргументов nargs извлекаются из стека операндов, и обработчик метода-цели вызывается. Вызов выполняется так же, как при выполнении инструкции invokevirtual, которая указывает индекс в постоянном пуле времени выполнения на символическую ссылку R, где:
-
R является символической ссылкой на метод класса;
-
для символической ссылки на класс, в котором должен находиться метод, R указывает
java.lang.invoke.MethodHandle; -
для имени метода R указывает
invokeExact; -
для описания метода R указывает описание метода в динамически вычисляемом месте вызова.
и где как будто следующие элементы в порядке поочередности записываются в стек операндов:
-
referenceк целевому обработчику метода; -
значения аргументов nargs, где количество, тип и порядок значений должны соответствовать описанию метода в динамически вычисляемом месте вызова.
Исключения при связывании
Во время разрешения символической ссылки на динамически вычисляемое место вызова может быть брошено любое из исключений, связанных с разрешением динамически вычисляемого места вызова.
Примечания
Если символическая ссылка на динамически вычисляемое место вызова может быть разрешена, это подразумевает, что не-null reference к экземпляру java.lang.invoke.CallSite связан с инструкцией invokedynamic. Следовательно, целевой обработчик метода, указанный экземпляром java.lang.invoke.CallSite, является не-null.
Аналогично, успешное разрешение подразумевает, что описание метода в символической ссылке семантически равно описанию типа целевого обработчика метода.
Вместе эти инварианты означают, что инструкция invokedynamic, которая связана с экземпляром java.lang.invoke.CallSite, никогда не вызывает исключение NullPointerException или java.lang.invoke.WrongMethodTypeException.
invokeinterface
Операция
Вызов метода интерфейса
Формат
invokeinterface
indexbyte1
indexbyte2
count
0
Формы
invokeinterface = 185 (0xb9)
Оперативная стопка
..., objectref, [arg1, [arg2 ...]] →
...
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на метод интерфейса (§5.1), которая содержит имя и дескриптор (§4.3.3) метода интерфейса, а также символическую ссылку на интерфейс, в котором находится метод интерфейса. Указанный метод интерфейса разрешается (§5.4.3.4).
Разрешенный метод интерфейса не должен быть методом инициализации экземпляра или методом инициализации класса или интерфейса (§2.9.1, §2.9.2).
Операнд count — это беззнаковый байт, который не должен быть равен нулю. objectref должен быть типа reference и за ним в стеке операндов должны следовать nargs значений аргументов, где количество, тип и порядок значений должны соответствовать дескриптору разрешенного метода интерфейса. Значение четвертого операндного байта должно всегда быть равно нулю.
Пусть C — класс objectref. Метод выбирается относительно C и разрешенного метода (§5.4.6). Это вызываемый метод.
Если вызываемый метод является synchronized, то монитор, связанный с objectref, вводится или повторно вводится, как если бы выполнялась инструкция monitorenter (§monitorenter) в текущем потоке.
Если вызываемый метод не является native, значения nargs аргументов и objectref извлекаются из стека операндов. Для вызываемого метода создается новая рамка в стеке виртуальной машины Java. objectref и значения аргументов поочередно становятся значениями локальных переменных новой рамки, при этом objectref находится в локальной переменной 0, arg1 — в локальной переменной 1 (или, если arg1 типа long или double, в локальных переменных 1 и 2) и так далее. Затем новая рамка становится текущей, а виртуальная машина Java устанавливается на код первой инструкции вызываемого метода. Выполнение продолжается с первой инструкции метода.
Если вызываемый метод является 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 будет прямым суперклассом текущего класса:
В противном случае, пусть C будет классом или интерфейсом, указанным в символической ссылке.
Фактический вызываемый метод выбирается по следующей процедуре поиска:
-
Если C содержит объявление метода экземпляра с тем же именем и дескриптором, что и разрешенный метод, то это вызываемый метод.
-
В противном случае, если C является классом и имеет суперкласс, выполняется поиск объявления метода экземпляра с тем же именем и дескриптором, что и разрешенный метод, начиная с непосредственного суперкласса C и продолжая с непосредственного суперкласса этого класса и так далее, пока не будет найдено совпадение или не останется других суперклассов. Если совпадение найдено, то это вызываемый метод.
-
В противном случае, если C является интерфейсом, и класс
Objectсодержит объявлениеpublicметода экземпляра с тем же именем и дескриптором, что и разрешенный метод, то это вызываемый метод. -
В противном случае, если существует ровно один максимально-специфический метод (§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 устанавливает код операции первого оператора вызываемого метода. Выполнение продолжается с первого оператора метода.
Если метод является native, и зависящий от платформы код, который его реализует, еще не привязан (§5.6) к виртуальной машине Java, это делается. Значения аргументов nargs извлекаются из стека операндов и передаются в качестве параметров коду, который реализует метод. Параметры передаются, и код вызывается способом, зависящим от реализации. Когда зависящий от платформы код возвращает значение, происходит следующее:
-
Если метод
nativeявляетсяsynchronized, монитор, связанный с разрешенным объектомClass, обновляется и, возможно, выводится как будто выполняется инструкция monitorexit (§monitorexit) в текущем потоке. -
Если метод
nativeвозвращает значение, значение возврата кода, зависящего от платформы, преобразуется способом, зависящим от реализации, в возвращаемый тип методаnativeи помещается в стек операндов.
Исключения связывания
Во время разрешения символической ссылки на метод могут быть выброшены исключения, связанные с разрешением методов (§5.4.3.3).
В противном случае, если разрешенный метод является методом экземпляра, инструкция invokestatic выбрасывает исключение IncompatibleClassChangeError.
Исключения во время выполнения
В противном случае, если выполнение этой инструкции invokestatic вызывает инициализацию ссылаемого класса или интерфейса, invokestatic может выбросить исключение Error, как подробно описано в §5.5.
В противном случае, если разрешенный метод является native и код, реализующий метод, не может быть привязан, invokestatic выбрасывает исключение UnsatisfiedLinkError.
Примечания
Значения аргументов nargs не являются взаимно однозначным соответствием с первыми nargs локальными переменными. Значения аргументов типов long и double должны храниться в двух последовательных локальных переменных, поэтому для передачи nargs значений аргументов вызываемому методу может потребоваться больше, чем nargs локальных переменных.
invokevirtual
Операция
Вызов метода экземпляра; диспетчеризация на основе класса
Формат
invokevirtual
indexbyte1
indexbyte2
Формы
invokevirtual = 182 (0xb6)
Стек операндов
..., objectref, [arg1, [arg2 ...]] →
...
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пул постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения по этому индексу должен быть символической ссылкой на метод (§5.1), который предоставляет имя и дескриптор (§4.3.3) метода, а также символическую ссылку на класс, в котором находится метод. Указанный метод разрешается (§5.4.3.3).
Если разрешенный метод не полиморфен по сигнатуре (§2.9.3), то инструкция invokevirtual выполняется следующим образом.
Пусть C — класс objectref. Выбирается метод относительно C и разрешенного метода (§5.4.6). Это вызываемый метод.
objectref должен следовать на стеке операндов nargs значениями аргументов, где количество, тип и порядок значений должны соответствовать дескриптору выбранного экземпляра метода.
Если вызываемый метод — synchronized, монитор, связанный с objectref, вводится или повторно вводится, как если бы была выполнена инструкция monitorenter (§monitorenter) в текущей потоке.
Если вызываемый метод не native, nargs значения аргументов и objectref извлекаются со стека операндов. На стеке виртуальной машины Java создается новая рамка для вызываемого метода. objectref и значения аргументов последовательно становятся значениями локальных переменных новой рамки, при этом objectref находится в локальной переменной 0, arg1 — в локальной переменной 1 (или, если arg1 имеет тип long или double, в локальных переменных 1 и 2) и так далее. Новая рамка затем становится текущей, и виртуальная машина Java pc устанавливается на код операции первой инструкции вызываемого метода. Выполнение продолжается с первой инструкции метода.
Если вызываемый метод — native, а зависящий от платформы код, который его реализует, еще не связан (§5.6) с виртуальной машиной Java, то это делается. nargs значения аргументов и objectref извлекаются со стека операндов и передаются в качестве параметров коду, реализующему метод. Параметры передаются, и код вызывается по реализации-зависимому способу. После того как код зависящий от платформы возвращает значение, происходит следующее:
-
Если
nativeметодsynchronized, монитор, связанный с objectref, обновляется и, возможно, выходит, как если бы была выполнена инструкция monitorexit (§monitorexit) в текущей потоке. -
Если
nativeметод возвращает значение, возвращаемое значение кода, зависящего от платформы, преобразуется способом, зависящим от реализации, в тип возвращаемого значенияnativeметода и помещается на стек операндов.
Если разрешенный метод является полиморфным по сигнатуре (§2.9.3), и объявлен в классе java.lang.invoke.MethodHandle, то инструкция invokevirtual выполняется следующим образом, где D — дескриптор метода, символически указанного в инструкции.
Сначала получают reference экземпляра java.lang.invoke.MethodType, как если бы произошло разрешение символической ссылки на тип метода (§5.4.3.5) с теми же параметрами и типами возвращаемых значений, что и D.
-
Если указанный метод является
invokeExact, экземплярjava.lang.invoke.MethodTypeдолжен быть семантически равен дескриптору типа получающего дескриптора метода objectref. Обрабатываемый дескриптор метода — это objectref. -
Если указанный метод является
invoke, и экземплярjava.lang.invoke.MethodTypeсемантически равен дескриптору типа получающего дескриптора метода objectref, то обрабатываемый дескриптор метода — это objectref. -
Если указанный метод является
invoke, и экземплярjava.lang.invoke.MethodTypeне семантически равен дескриптору типа получающего дескриптора метода objectref, виртуальная машина Java пытается скорректировать дескриптор типа получающего дескриптора метода, как если бы была вызвана методasTypeизjava.lang.invoke.MethodHandle, чтобы получить точно вызываемый дескриптор методаm. Обрабатываемый дескриптор метода — этоm.
objectref должен следовать на стеке операндов nargs значениями аргументов, где количество, тип и порядок значений должны соответствовать дескриптору типа вызываемого дескриптора метода. (Этот дескриптор типа будет соответствовать дескриптору метода, соответствующему типу дескриптора обрабатываемого метода, как указано в §5.4.3.5.)
Затем, если дескриптор метода имеет байткодовый метод, виртуальная машина Java вызывает дескриптор метода как если бы это происходило при выполнении байткодового поведения, связанного с видом дескриптора метода. Если вид — 5 (REF_invokeVirtual), 6 (REF_invokeStatic), 7 (REF_invokeSpecial), 8 (REF_newInvokeSpecial) или 9 (REF_invokeInterface), тогда рамка будет создана и станет текущей в ходе выполнения байткодового поведения; однако, эта рамка не видна, и когда метод, вызванный байткодовым поведением, завершается (обычно или внезапно), рамка его вызывателя считается рамкой для метода, содержащего эту инструкцию invokevirtual.
В противном случае, если дескриптор метода не имеет байткодового поведения, виртуальная машина Java вызывает его по реализации-зависимому способу.
Если разрешенный метод является полиморфным по сигнатуре и объявлен в классе java.lang.invoke.VarHandle, то инструкция invokevirtual выполняется следующим образом, где N и D — имя и дескриптор метода, символически указанного в инструкции.
Сначала получают reference экземпляра java.lang.invoke.VarHandle.AccessMode, как если бы была вызвана метод valueFromMethodName из java.lang.invoke.VarHandle.AccessMode с аргументом String, обозначающим N.
Во-вторых, получают reference экземпляра java.lang.invoke.MethodType, как если бы была вызвана метод accessModeType из java.lang.invoke.VarHandle на экземпляре objectref, с экземпляром java.lang.invoke.VarHandle.AccessMode в качестве аргумента.
В-третьих, получают reference экземпляра java.lang.invoke.MethodHandle, как если бы была вызвана метод varHandleExactInvoker из java.lang.invoke.MethodHandles с экземпляром java.lang.invoke.VarHandle.AccessMode в качестве первого аргумента и экземпляром java.lang.invoke.MethodType в качестве второго аргумента. Результирующий экземпляр называется обрабатываемый дескриптор метода.
Наконец, nargs значения аргументов и objectref извлекаются со стека операндов, и обрабатываемый дескриптор метода вызывается. Вызов происходит так, как если бы была выполнена инструкция invokevirtual, которая указывает индекс пула постоянных времени выполнения на символическую ссылку R, где:
-
R — это символическая ссылка на метод класса;
-
для символической ссылки на класс, в котором должен находиться метод, R указывает
java.lang.invoke.MethodHandle; -
для имени метода, R указывает
invoke; -
для описателя метода, R указывает возвращаемый тип, указанный возвращающим описателем D, и указывает тип первого параметра
java.lang.invoke.VarHandle, за которым следуют типы параметров, указанные описателями параметров D (если таковые имеются) в порядке следования.
и где, как если бы следующие элементы в указанном порядке были помещены на стек операндов:
-
ссылка
referenceна экземплярjava.lang.invoke.MethodHandle(обработчик метода-вызывающего); -
objectref;
-
значения аргументов nargs, где количество, тип и порядок значений должны соответствовать описателю типа обработчика метода-вызывающего.
Исключения при линковке
Во время разрешения символической ссылки на метод могут быть выброшены любые исключения, связанные с разрешением метода (§5.4.3.3).
В противном случае, если разрешённый метод — это метод класса (static), инструкция invokevirtual выбросит исключение IncompatibleClassChangeError.
В противном случае, если разрешенный метод полиморфен по сигнатуре и объявлен в классе java.lang.invoke.MethodHandle, то во время разрешения типа метода, полученного из описателя в символической ссылке на метод, могут быть выброшены любые исключения, связанные с разрешением типа метода (§5.4.3.5).
В противном случае, если разрешенный метод полиморфен по сигнатуре и объявлен в классе java.lang.invoke.VarHandle, то может быть выброшено любое исключение при линковке, которое может возникнуть в результате вызова обработчика метода-вызывающего. Никакие исключения при линковке не генерируются при вызове методов valueFromMethodName, accessModeType и varHandleExactInvoker.
Исключения во время выполнения
В противном случае, если objectref — это null, инструкция invokevirtual генерирует исключение NullPointerException.
В противном случае, если разрешенный метод не полиморфен по сигнатуре:
-
Если выбранный метод — это
abstract, invokevirtual генерирует исключениеAbstractMethodError. -
В противном случае, если выбранный метод — это
nativeи код, реализующий метод, не может быть привязан, invokevirtual генерирует исключениеUnsatisfiedLinkError. -
В противном случае, если метод не выбран, и существует несколько максимально-специфичных методов суперинтерфейса C, которые соответствуют имени и описателю разрешенного метода и не являются
abstract, invokevirtual выбросит исключениеIncompatibleClassChangeError. -
В противном случае, если метод не выбран и нет максимально-специфичных методов суперинтерфейсов C, которые соответствуют имени и описателю разрешенного метода и не являются
abstract, invokevirtual генерирует исключениеAbstractMethodError.
В противном случае, если разрешенный метод полиморфен по сигнатуре и объявлен в классе java.lang.invoke.MethodHandle, то:
-
Если имя метода — это
invokeExact, и полученный экземплярjava.lang.invoke.MethodTypeне является семантически равным описателю типа получающего обработчика метода objectref, инструкция invokevirtual генерирует исключениеjava.lang.invoke.WrongMethodTypeException. -
Если имя метода — это
invoke, и полученный экземплярjava.lang.invoke.MethodTypeне является допустимым аргументом для методаasTypeклассаjava.lang.invoke.MethodHandle, вызванного на получающем обработчике метода objectref, инструкция invokevirtual генерирует исключениеjava.lang.invoke.WrongMethodTypeException.
В противном случае, если разрешенный метод полиморфен по сигнатуре и объявлен в классе java.lang.invoke.VarHandle, то любое исключение во время выполнения, которое может возникнуть при вызове обработчика метода-вызывающего, может быть выброшено. Никакие исключения во время выполнения не генерируются при вызове методов valueFromMethodName, accessModeType и varHandleExactInvoker, за исключением NullPointerException, если objectref является null.
Примечания
Значения аргументов nargs и objectref не являются взаимно однозначными с первыми nargs+1 локальными переменными. Значения аргументов типов long и double должны храниться в двух последовательных локальных переменных, следовательно, для передачи nargs значений аргументов вызываемому методу может потребоваться больше, чем nargs локальных переменных.
Возможна ситуация, когда символическая ссылка инструкции invokevirtual указывает на метод интерфейса. В таком случае, возможно, нет переопределенного метода в иерархии классов, но метод интерфейса, не являющийся abstract, соответствует описателю разрешенного метода. Логика выбора соответствует такому методу, используя те же правила, что и для invokeinterface.
ior
Операция
Побитовое ИЛИ int
Формат
ior
Формы
ior = 128 (0x80)
Стек операндов
..., value1, value2 →
..., result
Описание
И value1, и value2 должны быть типа int. Они извлекаются из стека операндов. Вычисляется побитовое включительно ИЛИ value1 и value2, и результат result помещается на стек операндов.
irem
Операция
Остаток от деления int
Формат
irem
Формы
irem = 112 (0x70)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба value1 и value2 должны быть типа int. Значения извлекаются из стека операндов. Результат result вычисляется как value1 - (value1 / value2) * value2. Результат result помещается в стек операндов.
Результат инструкции irem таков, что (a/b)*b
+ (a%b) равно a. Это тождество выполняется и в особом случае, когда делимое является отрицательным int наибольшего возможного значения для его типа, а делитель равен -1 (остаток равен 0). Из этого правила следует, что результат операции взятия остатка может быть отрицательным только если делимое отрицательно и может быть положительным только если делимое положительно. Кроме того, величина результата всегда меньше величины делителя.
Исключение во время выполнения
Если значение делителя для оператора взятия остатка int равно 0, irem вызывает исключение ArithmeticException.
ireturn
Операция
Возврат int из метода
Формат
ireturn
Формы
ireturn = 172 (0xac)
Стек операндов
..., value →
[пусто]
Описание
Текущий метод должен иметь тип возвращаемого значения boolean, byte, char, short или int. value должен быть типа int. Если текущий метод является методом synchronized, то монитор, введённый или повторно введённый при вызове метода, обновляется и, возможно, выходит, как если бы выполнялась инструкция monitorexit (§monitorexit) в текущем потоке. Если исключение не возникает, value извлекается из стека операндов текущей рамки (§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.
ishr
Операция
Арифметический сдвиг вправо int
Формат
ishr
Формы
ishr = 122 (0x7a)
Стек операндов
..., value1, value2 →
..., result
Описание
Both value1 and value2 must be of type int. The values are popped from the operand stack. An int result is calculated by shifting value1 right by s bit positions, with sign extension, where s is the value of the low 5 bits of value2. The result is pushed onto the operand stack.
Примечания
The resulting value is floor(value1 / 2s), where s is value2 & 0x1f. For non-negative value1, this is equivalent to truncating int division by 2 to the power s. The shift distance actually used is always in the range 0 to 31, inclusive, as if value2 were subjected to a bitwise logical AND with the mask value 0x1f.
istore
Операция
Сохранить int в локальную переменную
Формат
istore
index
Формы
istore = 54 (0x36)
Стек операндов
..., value →
...
Описание
The index is an unsigned byte that must be an index into the local variable array of the current frame (§2.6). The value on the top of the operand stack must be of type int. It is popped from the operand stack, and the value of the local variable at index is set to value.
Примечания
The istore opcode can be used in conjunction with the wide instruction (§wide) to access a local variable using a two-byte unsigned index.
istore_<n>
Операция
Сохранить int в локальную переменную
Формат
istore_<n>
Формы
istore_0 = 59 (0x3b)
istore_1 = 60 (0x3c)
istore_2 = 61 (0x3d)
istore_3 = 62 (0x3e)
Стек операндов
..., value →
...
Описание
The <n> must be an index into the local variable array of the current frame (§2.6). The value on the top of the operand stack must be of type int. It is popped from the operand stack, and the value of the local variable at <n> is set to value.
Примечания
Each of the istore_<n> instructions is the same as istore with an index of <n>, except that the operand <n> is implicit.
isub
Операция
Вычесть int
Формат
isub
Формы
isub = 100 (0x64)
Стек операндов
..., value1, value2 →
..., result
Описание
Both value1 and value2 must be of type int. The values are popped from the operand stack. The int result is value1 - value2. The result is pushed onto the operand stack.
For int subtraction, a-b produces the same result as a+(-b). For int values, subtraction from zero is the same as negation.
The result is the 32 low-order bits of the true mathematical result in a sufficiently wide two's-complement format, represented as a value of type int. If overflow occurs, then the sign of the result may not be the same as the sign of the mathematical difference of the two values.
Despite the fact that overflow may occur, execution of an isub instruction never throws a run-time exception.
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.
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. Эти значения извлекаются из стека операндов. Результат типа long равен значение1 + значение2. Результат помещается в стек операндов.
Результат — это 64 младших бита истинного математического результата в достаточно широком формате дополнения до двух, представленного как значение типа long. Если происходит переполнение, знак результата может не совпадать со знаком математической суммы двух значений.
Несмотря на то, что переполнение может произойти, выполнение инструкции ladd никогда не генерирует исключение во время выполнения.
laload
Операция
Загрузка long из массива
Формат
laload
Формы
laload = 47 (0x2f)
Стек операндов
..., ссылкаНаМассив, индекс →
..., значение
Описание
СсылкаНаМассив должна быть типа reference и должна ссылаться на массив, компоненты которого имеют тип long. Индекс должен быть типа int. Обе ссылкаНаМассив и индекс извлекаются из стека операндов. Значение типа long в компоненте массива по индексу извлекается и помещается в стек операндов.
Исключения во время выполнения
Если ссылкаНаМассив является 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 является null, lastore генерирует исключение NullPointerException.
В противном случае, если index выходит за пределы массива, ссылаемого на arrayref, инструкция lastore генерирует исключение ArrayIndexOutOfBoundsException.
lcmp
Операция
Сравнение long
Формат
lcmp
Формы
lcmp = 148 (0x94)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба value1 и value2 должны быть типа long. Они извлекаются из стека операндов, и выполняется сравнение целых чисел со знаком. Если value1 больше value2, в стек операндов помещается значение 1. Если value1 равно value2, в стек операндов помещается значение 0. Если value1 меньше value2, в стек операндов помещается значение -1.
lconst_<l>
Операция
Поместить long константу
Формат
lconst_<l>
Формы
lconst_0 = 9 (0x9)
lconst_1 = 10 (0xa)
Стек операндов
... →
..., <l>
Описание
Поместить long константу <l> (0 или 1) в стек операндов.
ldc
Операция
Поместить элемент из пула констант во время выполнения
Формат
ldc
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)
Стек операндов
... →
..., значение
Описание
Беззнаковые indexbyte1 и indexbyte2 собираются в 16-битный беззнаковый индекс в пуле констант текущего класса (§2.5.5), где значение индекса вычисляется как (indexbyte1 << 8) | indexbyte2. Индекс должен быть допустимым индексом в пуле констант текущего класса. Элемент пула констант по этому индексу должен быть загружаемым (§5.1), и, в частности, быть одним из следующих:
-
Числовая константа типа
longилиdouble. -
Символическая ссылка на динамически вычисляемую константу, описание поля которой —
J(обозначающаяlong) илиD(обозначающаяdouble).
Если элемент пула констант — числовая константа типа long или double, то значение этой числовой константы помещается в стек операндов в качестве long или double соответственно.
В противном случае элемент пула констант — символическая ссылка на динамически вычисляемую константу. Символическая ссылка разрешается (§5.4.3.6), и значение, являющееся результатом разрешения, помещается в стек операндов.
Исключения при линковке
Во время разрешения символической ссылки на динамически вычисляемую константу могут быть выброшены любые исключения, связанные с разрешением динамически вычисляемых констант.
Примечания
Существует только версия инструкции ldc2_w с расширенным индексом; нет инструкции ldc2, которая помещает long или double с однобайтовым индексом.
ldiv
Операция
Деление long
Формат
ldiv
Формы
ldiv = 109 (0x6d)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
И значение1, и значение2 должны быть типа long. Значения извлекаются из стека операндов. long результат — результат выражения языка программирования Java значение1 / значение2. Результат помещается в стек операндов.
Деление 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
индекс
Формы
lload = 22 (0x16)
Стек операндов
... →
..., значение
Описание
Индекс — это беззнаковый байт. И индекс, и индекс+1 должны быть индексами в массиве локальных переменных текущей фрейма (§2.6). Локальная переменная по индексу индекс должна содержать long. Значение локальной переменной по индексу индекс помещается в стек операндов.
Примечания
Инструкция 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
пар соответствия ключ-смещение...
Формы
lookupswitch = 171 (0xab)
Стек операндов
..., ключ →
...
Описание
Инструкция lookupswitch имеет переменную длину. Сразу после кода операции lookupswitch от 0 до 3 байт должны использоваться для заполнения, таким образом, чтобы defaultbyte1 начинался по адресу, кратно четырём байтам от начала текущего метода (кода первой инструкции). Сразу после заполнения следуют ряд знаковых 32-битных значений: default, npairs, а затем npairs пар знаковых 32-битных значений. npairs должно быть больше или равно 0. Каждая из npairs пар состоит из match и знакового 32-битного offset. Каждое из этих знаковых 32-битных значений конструируется из четырёх беззнаковых байтов как (byte1 int 24) | (byte2 << 16) | (byte3 << 8) | byte4.
Таблица пар match-offset инструкции lookupswitch должна быть отсортирована по возрастанию match.
ключ должен быть типа int и извлекается из стека операндов. ключ сравнивается со значениями match. Если он равен одному из них, то целевой адрес вычисляется путём добавления соответствующего offset к адресу кода операции этой инструкции lookupswitch. Если ключ не совпадает ни с одним из значений match, то целевой адрес вычисляется путём добавления default к адресу кода операции этой инструкции lookupswitch. Выполнение затем продолжается по целевому адресу.
Целевой адрес, который может быть вычислен из offset каждой пары match-offset, а также тот, который вычислен из default, должен быть адресом кода операции инструкции внутри метода, который содержит эту инструкцию lookupswitch.
Примечания
Требуемое выравнивание 4-байтовых операндов инструкции lookupswitch гарантирует 4-байтовое выравнивание этих операндов тогда и только тогда, когда метод, содержащий lookupswitch, расположен на границе в 4 байта.
Пары match-offset отсортированы для поддержки процедур поиска, которые быстрее, чем линейный поиск.
lor
Операция
Булево ИЛИ long
Формат
lor
Формы
lor = 129 (0x81)
Стек операндов
..., value1, value2 →
..., результат
Описание
Оба value1 и value2 должны быть типа long. Они извлекаются из стека операндов. результат рассчитывается путём побитового включительно ИЛИ value1 и value2. результат помещается в стек операндов.
lrem
Операция
Остаток long
Формат
lrem
Формы
lrem = 113 (0x71)
Стек операндов
..., value1, value2 →
..., результат
Описание
Оба value1 и value2 должны быть типа long. Значения извлекаются из стека операндов. результат равен value1 - (value1 / value2) * value2. результат помещается в стек операндов.
Результат инструкции lrem таков, что (a/b)*b + (a%b) равен a. Это тождество выполняется даже в специальном случае, когда делимое является отрицательным long наибольшего возможного размера для его типа, а делитель — -1 (остаток равен 0). Из этого правила следует, что результат операции взятия остатка может быть отрицательным только если делимое отрицательное, и может быть положительным только если делимое положительное; кроме того, модуль результата всегда меньше модуля делителя.
Исключение во время выполнения
Если значение делителя для оператора взятия остатка long равно 0, lrem вызывает ArithmeticException.
lreturn
Операция
Возвращение long из метода
Формат
lreturn
Формы
lreturn = 173 (0xad)
Стек операндов
..., value →
[пустой]
Описание
Текущий метод должен иметь тип возвращаемого значения long. value должен быть типа long. Если текущий метод является методом synchronized, то монитор, вошедший или повторно вошедший при вызове метода, обновляется и, возможно, выходит, как если бы выполнилась инструкция monitorexit (§monitorexit) в текущем потоке. Если исключение не возникает, value извлекается из стека операндов текущей рамки (§2.6) и помещается в стек операндов рамки вызывающего метода. Любые другие значения в стеке операндов текущего метода отбрасываются.
Затем интерпретатор возвращает управление вызывающему методу, восстанавливая рамку вызывающего метода.
Исключения во время выполнения
Если реализация Java Virtual Machine не соблюдает правила структурированного блокирования, описанные в §2.11.10, то если текущий метод является методом synchronized, и текущий поток не является владельцем монитора, вошедшего или повторно вошедшего при вызове метода, lreturn генерирует исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит инструкцию monitorexit, но не инструкцию monitorenter, по объекту, к которому метод synchronized.
В противном случае, если реализация Java Virtual Machine соблюдает правила структурированного блокирования, описанные в §2.11.10, и если первое из этих правил нарушается во время вызова текущего метода, то lreturn генерирует исключение IllegalMonitorStateException.
lshl
Операция
Сдвиг влево long
Формат
lshl
Формы
lshl = 121 (0x79)
Стек операндов
..., value1, value2 →
..., result
Описание
value1 должен быть типа long, а value2 — типа int. Значения извлекаются из стека операндов. Результат 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)
Стек операндов
..., value →
...
Описание
И <n>, и <n>+1 должны быть индексами в массиве локальных переменных текущей рамки (§2.6). Значение value на вершине стека операндов должно быть типа long. Оно извлекается из стека операндов, а локальные переменные по индексам <n> и <n>+1 устанавливаются в значение value.
Примечания
Каждая из инструкций lstore_<n> идентична инструкции lstore с индексом <n>, за исключением того, что операнд <n> является неявным.
lsub
Операция
Вычитание long
Формат
lsub
Формы
lsub = 101 (0x65)
Стек операндов
..., value1, value2 →
..., result
Описание
И value1, и value2 должны быть типа long. Значения извлекаются из стека операндов. Результат result вычисляется как value1 - value2. Результат result помещается в стек операндов.
Для вычитания long, a-b производит тот же результат, что и a+(-b). Для long значений вычитание из нуля равно отрицанию.
Результат представляет собой 64 младших бита истинного математического результата в достаточном широком формате со знаком, представленном значением типа long. Если происходит переполнение, то знак результата может не совпадать со знаком математической разницы двух значений.
Несмотря на то, что переполнение может произойти, выполнение инструкции lsub никогда не генерирует исключение во время выполнения.
lushr
Операция
Логический сдвиг вправо long
Формат
lushr
Формы
lushr = 125 (0x7d)
Стек операндов
..., value1, value2 →
..., result
Описание
value1 должен быть типа long, а value2 — типа int. Значения извлекаются из стека операндов. Вычисляется значение result путём логического сдвига value1 вправо на s битовых позиций с нулевым расширением, где s — значение 6 младших битов value2. Результат result помещается в стек операндов.
Примечания
Если value1 положительно, а s равно value2 & 0x3f, результат совпадает с результатом value1 >> s; если value1 отрицательно, результат равен значению выражения (value1 >> s) + (2L << ~s). Добавление (2L << ~s) компенсирует распространяемый бит знака. Расстояние сдвига, фактически используемое, всегда находится в диапазоне от 0 до 63 включительно.
lxor
Операция
Булево XOR long
Формат
lxor
Формы
lxor = 131 (0x83)
Стек операндов
..., value1, value2 →
..., result
Описание
И value1, и value2 должны быть типа long. Они извлекаются из стека операндов. Значение result вычисляется как побитовое исключающее ИЛИ value1 и value2. Результат result помещается в стек операндов.
monitorenter
Операция
Вход в монитор объекта
Формат
monitorenter
Формы
monitorenter = 194 (0xc2)
Стек операндов
..., objectref →
...
Описание
objectref должен быть типа reference.
Каждый объект связан с монитором. Монитор заблокирован тогда и только тогда, когда у него есть владелец. Поток, выполняющий monitorenter, пытается получить владение монитором, связанным с objectref, следующим образом:
-
Если счётчик входов в монитор, связанный с objectref, равен нулю, поток входит в монитор и устанавливает счётчик входов в единицу. Поток затем становится владельцем монитора.
-
Если поток уже владеет монитором, связанным с objectref, он повторно входит в монитор, увеличивая счётчик входов.
-
Если другой поток уже владеет монитором, связанным с objectref, поток блокируется до тех пор, пока счётчик входов монитора не станет нулём, а затем пытается снова получить владение.
Исключение во время выполнения
Если objectref является null, monitorenter генерирует исключение NullPointerException.
Примечания
Инструкция monitorenter может использоваться с одной или несколькими инструкциями monitorexit (§monitorexit) для реализации оператора `synchronized` в языке программирования Java (§3.14). Инструкции monitorenter и monitorexit не используются в реализации методов, использующих блокировку synchronized, хотя их можно использовать для обеспечения эквивалентной семантики блокировки. Вход в монитор при вызове метода synchronized и выход из монитора при его возвращении обрабатываются неявно механизмом вызова и возврата метода Java Virtual Machine, как если бы использовались monitorenter и monitorexit.
Связь монитора с объектом может управляться различными способами, которые выходят за рамки данной спецификации. Например, монитор может быть выделен и освобождён одновременно с объектом. В качестве альтернативы, он может быть динамически выделен в момент попытки потока получить эксклюзивный доступ к объекту и освобождён в какой-либо момент в будущем, когда в мониторе для объекта больше нет потоков.
Конструкции синхронизации языка программирования Java требуют поддержки операций с мониторами помимо входа и выхода. К ним относятся ожидание на мониторе (Object.wait) и уведомление других потоков, ожидающих на мониторе (Object.notifyAll и Object.notify). Эти операции поддерживаются в стандартном пакете java.lang, поставляемом с Java Virtual Machine. В наборе инструкций Java Virtual Machine явной поддержки этих операций нет.
monitorexit
Операция
Выход из монитора объекта
Формат
monitorexit
Формы
monitorexit = 195 (0xc3)
Стек операндов
..., objectref →
...
Описание
objectref должен быть типа reference.
Поток, выполняющий monitorexit, должен быть владельцем монитора, связанного с экземпляром, на который ссылается objectref.
Поток декрементирует счётчик входов в монитор, связанный с objectref. Если в результате значение счётчика равно нулю, поток выходит из монитора и больше не является его владельцем. Другие потоки, блокированные для входа в монитор, могут попытаться сделать это.
Исключения во время выполнения
Если objectref является null, monitorexit генерирует исключение NullPointerException.
В противном случае, если поток, выполняющий monitorexit, не является владельцем монитора, связанного с экземпляром, на который ссылается objectref, monitorexit генерирует исключение IllegalMonitorStateException.
В противном случае, если реализация Java Virtual Machine выполняет правила структурированной блокировки, описанные в §2.11.10, и если второе из этих правил нарушается выполнением этой инструкции monitorexit, то monitorexit генерирует исключение IllegalMonitorStateException.
Примечания
Одна или несколько инструкций monitorexit могут использоваться с инструкцией monitorenter (§monitorenter) для реализации оператора `synchronized` в языке программирования Java (§3.14). Инструкции monitorenter и monitorexit не используются в реализации методов, использующих блокировку synchronized, хотя их можно использовать для обеспечения эквивалентной семантики блокировки.
Java Virtual Machine поддерживает исключения, генерируемые внутри методов synchronized и операторов synchronized по-разному:
-
Выход из монитора при нормальном завершении метода
synchronizedобрабатывается инструкциями возврата Java Virtual Machine. Выход из монитора при внезапном завершении методаsynchronizedобрабатывается неявно инструкцией athrow Java Virtual Machine. -
Когда исключение генерируется внутри оператора
synchronized, выход из монитора, в который вошли до выполнения оператораsynchronized, достигается с помощью механизма обработки исключений Java Virtual Machine (§3.14).
multianewarray
Операция
Создание нового многомерного массива
Формат
multianewarray
indexbyte1
indexbyte2
dimensions
Формы
multianewarray = 197 (0xc5)
Стек операндов
..., count1, [count2, ...] →
..., arrayref
Описание
Операнд dimensions — это байт без знака, который должен быть больше или равен 1. Он представляет количество измерений создаваемого массива. Стек операндов должен содержать dimensions значений. Каждое такое значение представляет количество компонентов в измерении создаваемого массива, должно быть типа int и должно быть неотрицательным. count1 — желаемая длина в первом измерении, count2 — во втором и т. д.
Все значения count извлекаются из стека операндов. Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на класс, массив или тип интерфейса. Имя класса, массива или типа интерфейса разрешается (§5.4.3.1). Результирующий элемент должен быть типом класса массива размерности, большей или равной dimensions.
Новый многомерный массив указанного типа выделяется из кучи сборки мусора. Если какое-либо значение count равно нулю, последующие измерения не выделяются. Компоненты массива в первом измерении инициализируются подмассивами типа второго измерения и так далее. Компоненты последнего выделенного измерения массива инициализируются значением по умолчанию (§2.3, §2.4) для типа элементов типа массива. Ссылка arrayref на новый массив помещается на стек операндов.
Исключения при связывании
При разрешении символической ссылки на класс, массив или тип интерфейса могут быть выброшены любые исключения, описанные в §5.4.3.1.
В противном случае, если текущий класс не имеет разрешения на доступ к типу элемента разрешенного класса массива, инструкция multianewarray генерирует исключение IllegalAccessError.
Исключение во время выполнения
В противном случае, если какое-либо из значений dimensions на стеке операндов меньше нуля, инструкция multianewarray генерирует исключение NegativeArraySizeException.
Примечания
Для создания массива с одним измерением может быть эффективнее использовать инструкции newarray или anewarray (§newarray, §anewarray).
Класс массива, на который ссылаются через постоянный пул времени выполнения, может иметь больше измерений, чем операнд dimensions инструкции multianewarray. В этом случае создаются только первые dimensions измерений массива.
new
Операция
Создание нового объекта
Формат
new
indexbyte1
indexbyte2
Формы
new = 187 (0xbb)
Стек операндов
... →
..., objectref
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на тип класса или интерфейса. Имя класса или интерфейса разрешается (§5.4.3.1) и должно привести к типу класса. Память для нового экземпляра этого класса выделяется из кучи сборки мусора, а переменные экземпляра нового объекта инициализируются значениями по умолчанию (§2.3, §2.4). Ссылка objectref на экземпляр помещается на стек операндов.
При успешном разрешении класса, он инициализируется, если не был инициализирован ранее (§5.5).
Исключения при связывании
При разрешении символической ссылки на тип класса или интерфейса могут быть выброшены любые исключения, описанные в §5.4.3.1.
В противном случае, если символическая ссылка на тип класса или интерфейса разрешается на интерфейс или абстрактный класс, инструкция new генерирует исключение 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 должно быть типа, совместимого с типом дескриптора поля по присваиванию (JLS §5.2). Если поле является final, оно должно быть объявлено в текущем классе, и инструкция должна находиться в методе инициализации экземпляра текущего класса (§2.9.1).
Значения value и objectref извлекаются из стека операндов.
objectref должен быть типа reference, но не типа массива.
Если value имеет тип int, а тип дескриптора поля – boolean, то значение value сужается путем взятия побитовой конъюнкции value и 1, что приводит к value'. Ссылающееся поле в objectref устанавливается в value'.
В противном случае ссылающееся поле в objectref устанавливается в value.
Исключения связывания
Во время разрешения символической ссылки на поле могут быть выброшены исключения, относящиеся к разрешению поля (§5.4.3.2).
В противном случае, если разрешенное поле является полем static, putfield выбрасывает исключение IncompatibleClassChangeError.
В противном случае, если разрешенное поле является final, оно должно быть объявлено в текущем классе, а инструкция должна находиться в методе инициализации экземпляра текущего класса. В противном случае выбрасывается исключение IllegalAccessError.
Исключение времени выполнения
В противном случае, если objectref имеет значение null, инструкция putfield выбрасывает исключение NullPointerException.
putstatic
Операция
Установка статического поля в классе
Формат
putstatic
indexbyte1
indexbyte2
Формы
putstatic = 179 (0xb3)
Оперативная область стека
..., значение →
...
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на поле (§5.1), которая задаёт имя и дескриптор поля, а также символическую ссылку на класс или интерфейс, в котором это поле находится. Ссылаемое поле разрешается (§5.4.3.2).
При успешном разрешении поля, класс или интерфейс, объявивший разрешённое поле, инициализируется, если этот класс или интерфейс ещё не был инициализирован (§5.5).
Тип значение, хранимого инструкцией putstatic, должен быть совместим с дескриптором ссылаемого поля (§4.3.2). Если тип дескриптора поля равен boolean, byte, char, short или int, то значение должно быть целым числом. Если тип дескриптора поля равен float, long или double, то значение должно быть целым числом, long или double соответственно. Если тип дескриптора поля — тип ссылки, то значение должно быть типа, совместимого с типом дескриптора поля (JLS §5.2). Если поле является final, оно должно быть объявлено в текущем классе или интерфейсе, и инструкция должна выполняться в методе инициализации класса или интерфейса текущего класса или интерфейса (§2.9.2).
Значение значение извлекается из стека операций.
Если значение имеет тип int, а тип дескриптора поля равен boolean, то значение значение сужается, вычисляя побитовую конъюнкцию значение и 1, что даёт значение значение'. Ссылаемое поле в классе или интерфейсе устанавливается в значение значение'.
В противном случае ссылаемое поле в классе или интерфейсе устанавливается в значение значение.
Исключения связывания
При разрешении символической ссылки на поле класса или интерфейса могут быть выброшены исключения, связанные с разрешением поля (§5.4.3.2).
В противном случае, если разрешенное поле не является полем класса (класса) или интерфейсом, 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. Содержимое локальной переменной записывается в регистр pc виртуальной машины Java, и выполнение продолжается оттуда.
Примечания
Обратите внимание, что jsr (§jsr) помещает адрес в оперативную область стека, а ret получает его из локальной переменной. Эта асимметрия является намеренной.
В реализации компилятора Oracle для языка программирования Java до Java SE 6 инструкция ret использовалась с инструкциями jsr и jsr_w (§jsr, §jsr_w) при реализации блока finally (§3.13, §4.10.2.5).
Инструкцию ret не следует путать с инструкцией return (§return). Инструкция return возвращает управление из метода его вызывающему объекту, не передавая ему никакого значения.
Операнд ret можно использовать совместно с инструкцией wide (§wide), чтобы обратиться к локальной переменной с помощью двухбайтного беззнакового индекса.
return
Операция
Возврат void из метода
Формат
return
Формы
return = 177 (0xb1)
Стек операндов
... →
[пусто]
Описание
Текущий метод должен иметь тип возвращаемого значения void. Если текущий метод является методом synchronized, монитор, введённый или повторно введённый при вызове метода, обновляется и, возможно, выходит, как если бы был выполнен оператор monitorexit (§monitorexit) в текущем потоке. Если исключение не выбрасывается, все значения в стеке операндов текущей рамки (§2.6) отбрасываются.
Затем интерпретатор возвращает управление вызывающему методу, восстанавливая рамку вызывающего метода.
Исключения во время выполнения
Если реализация Java Virtual Machine не применяет правила структурированной блокировки, описанные в §2.11.10, то если текущий метод является методом synchronized, а текущий поток не является владельцем монитора, введённого или повторно введённого при вызове метода, return выбрасывает исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит оператор monitorexit, но не оператор monitorenter, для объекта, по которому вызывается метод synchronized.
В противном случае, если реализация Java Virtual Machine применяет правила структурированной блокировки, описанные в §2.11.10, и если первое из этих правил нарушено при вызове текущего метода, то return выбрасывает исключение IllegalMonitorStateException.
saload
Операция
Загрузка short из массива
Формат
saload
Формы
saload = 53 (0x35)
Стек операндов
..., arrayref, index →
..., value
Описание
arrayref должен быть типа reference и должен ссылаться на массив, компоненты которого имеют тип short. index должен быть типа int. И arrayref, и index извлекаются из стека операндов. Извлекается компонент массива по индексу index и расширяется со знаком до int value. Это значение value помещается в стек операндов.
Исключения во время выполнения
Если arrayref является null, saload выбрасывает исключение NullPointerException.
В противном случае, если index не находится в пределах границ массива, на который ссылается arrayref, инструкция saload выбрасывает исключение ArrayIndexOutOfBoundsException.
sastore
Операция
Сохранение в массив short
Формат
sastore
Формы
sastore = 86 (0x56)
Стек операндов
..., arrayref, index, value →
...
Описание
arrayref должен быть типа reference и должен ссылаться на массив, компоненты которого имеют тип short. index и value должны быть типа int. arrayref, index и value извлекаются из стека операндов. Значение value усекается до short и сохраняется в качестве компонента массива с индексом index.
Исключения во время выполнения
Если arrayref является null, sastore выбрасывает исключение NullPointerException.
В противном случае, если index не находится в пределах границ массива, на который ссылается arrayref, инструкция sastore выбрасывает исключение ArrayIndexOutOfBoundsException.
sipush
Операция
Помещение short в стек
Формат
sipush
byte1
byte2
Формы
sipush = 17 (0x11)
Стек операндов
... →
..., value
Описание
Непосредственные значения byte1 и byte2 объединяются в промежуточное short, где значение short вычисляется как (byte1 << 8) | byte2. Промежуточное значение расширяется со знаком до int value. Это значение value помещается в стек операндов.
swap
Операция
Поменяйте верхние два значения стека операндов
Формат
swap
Формы
swap = 95 (0x5f)
Стек операндов
..., value2, value1 →
..., value1, value2
Описание
Поменяйте верхние два значения в стеке операндов.
Инструкция swap должна использоваться только в том случае, если value1 и value2 являются значениями вычислительного типа категории 1 (§2.11.1).
Примечания
Виртуальная машина Java не предоставляет инструкцию для обмена операндами вычислительных типов категории 2.
tableswitch
Операция
Доступ к таблице переходов по индексу и переход
Формат
tableswitch
<0-3 byte pad>
defaultbyte1
defaultbyte2
defaultbyte3
defaultbyte4
lowbyte1
lowbyte2
lowbyte3
lowbyte4
highbyte1
highbyte2
highbyte3
highbyte4
jump offsets...
Формы
tableswitch = 170 (0xaa)
Стек операндов
..., index →
...
Описание
Инструкция tableswitch имеет переменную длину. Сразу после кода операции tableswitch должны быть от 0 до 3 байт заполнения, так чтобы defaultbyte1 начинался по адресу, кратному четырем байтам от начала текущего метода (кода первой инструкции). Сразу после заполнения следуют байты, составляющие три подписанных 32-битных значения: default, low и high. Сразу за ними следуют байты, составляющие серию high - low + 1 подписанных 32-битных смещений. Значение low должно быть меньше или равно high. Подписанные 32-битные смещения трактуются как таблица переходов с нулевой базой. Каждое из этих подписанных 32-битных значений конструируется как (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4.
index должен быть типа int и извлекается из стека операндов. Если index меньше low или больше high, то адрес назначения вычисляется путем добавления default к адресу кода операции этой инструкции tableswitch. В противном случае извлекается смещение в позиции index - low таблицы переходов. Адрес назначения вычисляется путем добавления этого смещения к адресу кода операции этой инструкции tableswitch. Далее выполнение продолжается по адресу назначения.
Адрес назначения, который можно вычислить из каждого смещения таблицы переходов, а также из default, должен быть адресом кода операции инструкции в методе, содержащем эту инструкцию tableswitch.
Примечания
Требуемое выравнивание 4-байтовых операндов инструкции tableswitch гарантирует выравнивание этих операндов на 4 байта тогда и только тогда, когда метод, содержащий tableswitch, начинается с границ в 4 байта.
wide
Операция
Увеличить индекс локальной переменной на дополнительные байты
Формат 1
wide
<opcode>
indexbyte1
indexbyte2
где <opcode> — это один из iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore или ret
Формат 2
wide
iinc
indexbyte1
indexbyte2
constbyte1
constbyte2
Формы
wide = 196 (0xc4)
Стек операндов
Такой же, как у модифицированной инструкции
Описание
Инструкция wide изменяет поведение другой инструкции. Она принимает один из двух форматов, в зависимости от модифицируемой инструкции. Первый формат инструкции wide модифицирует одну из инструкций iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore или ret (§iload, §fload, §aload, §lload, §dload, §istore, §fstore, §astore, §lstore, §dstore, §ret). Второй формат применяется только к инструкции iinc (§iinc).
В любом случае, сам оператор wide в скомпилированном коде следует за кодом инструкции, которую wide модифицирует. В любом формате, за модифицированным кодом следуют два беззнаковых байта indexbyte1 и indexbyte2, которые собираются в 16-битный беззнаковый индекс локальной переменной в текущем фрейме (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Вычисленный индекс должен быть индексом в массив локальных переменных текущего фрейма. Где инструкция wide модифицирует инструкцию lload, dload, lstore или dstore, индекс, следующий за вычисленным индексом (индекс + 1), также должен быть индексом в массив локальных переменных. Во втором формате два беззнаковых байта constbyte1 и constbyte2 следуют за indexbyte1 и indexbyte2 в потоке кода. Эти байты также собираются в знаковое 16-битное константу, где константа равна (constbyte1 << 8) | constbyte2.
Расширенный байткод работает как обычно, за исключением использования расширенного индекса и, в случае второго формата, более широкого диапазона приращения.
Примечания
Хотя мы говорим, что wide "модифицирует поведение другой инструкции", инструкция wide фактически рассматривает байты, составляющие модифицированную инструкцию, как операнды, денатурируя встроенную инструкцию в этом процессе. В случае модифицированной инструкции iinc один из логических операндов iinc даже не находится в обычном смещении от оператора. Встроенная инструкция никогда не должна выполняться напрямую; её оператор никогда не должен быть целью никакой инструкции передачи управления.
© Oracle and/or its affiliates. All rights reserved.
Licensed under the Oracle Technology Network License Agreement.