Глава 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
- if_icmp
- if
- ifnonnull
- ifnull
- iinc
- iload
- iload_
- imul
- ineg
- instanceof
- invokedynamic
- invokeinterface
- invokespecial
- invokestatic
- invokevirtual
- ior
- irem
- ireturn
- ishl
- ishr
- fconst_
- istore
- istore_<n>
- isub
- iushr
- ixor
- jsr
- jsr_w
- l2d
- l2f
- l2i
- ladd
- laload
- land
- lastore
- lcmp
- lconst_<l>
- ldc
- ldc_w
- ldc2_w
- ldiv
- lload
- lload_<n>
- lmul
- lneg
- lookupswitch
- lor
- lrem
- lreturn
- lshl
- lshr
- lstore
- lstore_<n>
- lsub
- lushr
- lxor
- monitorenter
- monitorexit
- multianewarray
- new
- newarray
- nop
- pop
- pop2
- putfield
- putstatic
- ret
- return
- saload
- sastore
Инструкция виртуальной машины Java состоит из кода операции, определяющего выполняемое действие, за которым следуют ноль или более операндов, содержащих значения, над которыми выполняется операция. В этой главе подробно описан формат каждой инструкции виртуальной машины Java и выполняемая ею операция.
Описание каждой инструкции всегда даётся в контексте кода виртуальной машины Java, удовлетворяющего статическим и структурным ограничениям §4. В описании отдельных инструкций виртуальной машины Java мы часто говорим, что какая-либо ситуация «должна» или «не должна» быть: «Значение value2 должно быть типа int». Ограничения §4 гарантируют, что все подобные ожидания на самом деле будут выполнены. Если какое-либо ограничение («должен» или «не должен») в описании инструкции не выполняется во время выполнения, поведение виртуальной машины Java является неопределённым.
Виртуальная машина Java проверяет соответствие кода виртуальной машины Java статическим и структурным ограничениям во время компоновки, используя верификатор файла class (§4.10). Таким образом, виртуальная машина Java будет пытаться выполнить код только из допустимых файлов class. Выполнение верификации во время компоновки выгодно, так как проверки выполняются только один раз, что значительно сокращает объём работы, который необходимо выполнить во время выполнения. Другие стратегии реализации возможны при условии, что они соответствуют Спецификации языка Java, издание Java SE 7 и Спецификации виртуальной машины Java, издание Java SE 7.
В дополнение к кодам операций инструкций, указанных позднее в этой главе, которые используются в файлах class (§4), три кода операций зарезервированы для внутреннего использования реализацией виртуальной машины Java. Если набор инструкций виртуальной машины Java будет расширен в будущем, эти зарезервированные коды операций гарантированно не будут использоваться.
Два из зарезервированных кодов операций, номера 254 (0xfe) и 255 (0xff), имеют мнемоники impdep1 и impdep2 соответственно. Эти инструкции предназначены для предоставления «задних дверей» или ловушек для реализации функциональности, специфичной для реализации, реализованной в программном и аппаратном обеспечении соответственно. Третий зарезервированный код операции, номер 202 (0xca), имеет мнемонику breakpoint и предназначен для использования отладчиками для реализации точек останова.
Хотя эти коды операций зарезервированы, они могут использоваться только внутри реализации виртуальной машины Java. Они не могут появляться в допустимых файлах class. Инструменты, такие как отладчики или генераторы JIT-кода (§2.13), которые могут напрямую взаимодействовать с кодом виртуальной машины Java, который уже загружен и выполняется, могут столкнуться с этими кодами операций. Такие инструменты должны попытаться вести себя корректно, если они столкнутся с любой из этих зарезервированных инструкций.
Реализация Java виртуальной машины выбрасывает объект, являющийся экземпляром подкласса класса VirtualMethodError, когда внутренняя ошибка или ограничение ресурсов препятствуют выполнению семантики, описанной в этой главе. Этот спецификация не может предсказать, где могут возникнуть внутренние ошибки или ограничения ресурсов и не предписывает точное время их сообщения. Таким образом, любой из подклассов VirtualMethodError, определённых ниже, может быть сгенерирован в любое время во время работы Java виртуальной машины:
-
InternalError: В реализации Java виртуальной машины произошла внутренняя ошибка из-за сбоя в программном обеспечении, реализующем виртуальную машину, сбоя в программном обеспечении базовой системной среды или сбоя в оборудовании. Эта ошибка доставляется асинхронно (§2.10) при её обнаружении и может произойти в любой точке программы. -
OutOfMemoryError: Реализация Java виртуальной машины исчерпала виртуальную или физическую память, и автоматический менеджер хранения не смог вернуть достаточно памяти для удовлетворения запроса на создание объекта. -
StackOverflowError: Реализация Java виртуальной машины исчерпала стек памяти для потока, как правило, из-за неограниченного числа рекурсивных вызовов потока, вызванных сбоем в выполняемой программе. -
UnknownError: Произошло исключение или ошибка, но реализация Java виртуальной машины не может сообщить об истинном исключении или ошибке.
Инструкции виртуальной машины Java в этой главе представлены в виде записей, приведённых ниже в алфавитном порядке, каждая на новой странице.
мнемоника
Операция
Краткое описание инструкции
Формат
мнемоника
операнд1
операнд2
...
Формы
мнемоника = код операции
Стек операндов
..., значение1, значение2 →
..., значение3
Описание
Более подробное описание ограничений содержимого стека операндов или записей константного пула, выполняемой операции, типа результатов и т. п.
Исключения связывания
Если при выполнении данной инструкции могут быть выброшены исключения связывания, они перечислены по одной строке в порядке, в котором должны быть выброшены.
Исключения времени выполнения
Если при выполнении инструкции могут быть выброшены исключения времени выполнения, они перечислены по одной строке в порядке, в котором они должны быть выброшены.
Помимо исключений связывания и времени выполнения, указанных для инструкции, она не должна вызывать никаких исключений времени выполнения, кроме случаев VirtualMethodError или его подклассов.
Примечания
Комментарии, не являющиеся строго частью спецификации инструкции, отделены как примечания в конце описания.
Каждая ячейка в диаграмме формата инструкции представляет собой отдельный 8-битный байт. Мнемоника инструкции — её имя. Код операции — её числовое представление, приведённое в десятичной и шестнадцатеричной формах. В файле кода виртуальной машины Java фактически присутствует только числовое представление.
Помните, что «операнды» генерируются на этапе компиляции и встроены в инструкции виртуальной машины Java, а также «операнды», вычисляемые во время выполнения и предоставляемые в стеке операндов. Хотя они предоставляются из разных источников, все эти операнды представляют собой одни и те же данные: значения, над которыми выполняется инструкция виртуальной машины Java.
Виртуальная машина Java стремится к компактности кода, неявно получая многие операнды из своего стека операндов, а не представляя их явно в своём скомпилированном коде как дополнительные байты операндов, номера регистров и т. д.
Некоторые инструкции представлены как члены группы родственных инструкций, которые разделяют одно описание, формат и диаграмму стека операндов. Таким образом, группа инструкций включает несколько кодов операций и мнемоник кодов операций; в диаграмме формата инструкции отображается только мнемоника группы, а отдельная строка «Формы» перечисляет все мнемоники и коды операций членов группы. Например, строка «Формы» для группы инструкций lconst_<l>, предоставляющая мнемоническую и информацию о кодах операций для двух инструкций этой группы (lconst_0 и lconst_1), имеет вид:
lconst_0 = 9 (0x9)
lconst_1 = 10 (0xa)
При описании инструкций виртуальной машины Java воздействие выполнения инструкции на стек операндов (§2.6.2) текущей рамки (§2.6) представлено текстово, при этом стек растёт слева направо, и каждое значение представляется отдельно. Таким образом,
..., значение1, значение2 →
..., результат
показывает операцию, которая начинается с значения2 вверху стека операндов со значением1 прямо под ним. В результате выполнения команды значение1 и значение2 извлекаются из стека операндов и заменяются значением результат, вычисленным командой. Остальная часть стека операндов, представленная многоточием (...), не изменяется в результате выполнения команды.
Значения типов long и double представлены одной записью в стеке операндов.
В Спецификации виртуальной машины Java, первое издание, значения в стеке операндов типов long и double в диаграмме стека представлялись двумя записями.
aaload
Операция
Загрузка reference из массива
Формат
aaload
Формы
aaload = 50 (0x32)
Стек операндов
..., arrayref, index →
..., value
Описание
arrayref должен быть типа reference и должен ссылаться на массив, компоненты которого имеют тип reference. index должен быть типа int. Оба arrayref и index извлекаются из стека операндов. Значение reference value в компоненте массива по index извлекается и помещается в стек операндов.
Исключения во время выполнения
Если arrayref является null, aaload вызывает исключение NullPointerException.
В противном случае, если index не находится в пределах границ массива, на который ссылается arrayref, команда aaload генерирует исключение ArrayIndexOutOfBoundsException.
aastore
Операция
Запись в массив reference
Формат
aastore
Формы
aastore = 83 (0x53)
Стек операндов
..., arrayref, index, value →
...
Описание
arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип reference. index должен быть типа int, а значение – типа reference. arrayref, index и value извлекаются из стека операндов. Значение value сохраняется как компонент массива по индексу index.
Во время выполнения тип value должен быть совместим с типом компонентов массива, на который ссылается arrayref. Конкретно, присваивание значения типа ссылки S (источник) компоненту массива типа ссылки T (цель) разрешено только при выполнении следующих условий:
-
Если S – тип класса, то:
-
Если T – тип класса, то S должен быть тем же классом, что и T, или S должен быть подклассом T;
-
Если T – тип интерфейса, то S должен реализовывать интерфейс T.
-
-
Если S – тип интерфейса, то:
-
Если T – тип класса, то T должен быть
Object. -
Если T – тип интерфейса, то T должен быть тем же интерфейсом, что и S, или суперинтерфейсом S.
-
-
Если S – тип массива, а именно, тип SC
[], то есть массив компонентов типа SC, то:-
Если T – тип класса, то T должен быть
Object. -
Если T – тип интерфейса, то T должен быть одним из интерфейсов, реализуемых массивами (JLS §4.10.3).
-
Если T – тип массива TC
[], то есть массив компонентов типа TC, то одно из следующих условий должно быть истинным:-
TC и SC – один и тот же примитивный тип.
-
TC и SC – типы ссылок, и тип SC может быть приведён к типу TC по этим правилам выполнения.
-
-
Исключения во время выполнения
Если arrayref является null, aastore генерирует исключение NullPointerException.
В противном случае, если index не находится в пределах границ массива, на который ссылается arrayref, инструкция aastore генерирует исключение ArrayIndexOutOfBoundsException.
В противном случае, если arrayref не является null, и фактический тип value не совместим для присваивания (JLS §5.2) с фактическим типом компонентов массива, aastore генерирует исключение ArrayStoreException.
aconst_null
Операция
Положить null
Формат
aconst_null
Формы
aconst_null = 1 (0x1)
Стек операндов
... →
..., null
Описание
Положить объект null reference на стек операндов.
Примечания
Виртуальная машина Java не предписывает конкретное значение для null.
aload
Операция
Загрузить reference из локальной переменной
Формат
aload
index
Формы
aload = 25 (0x19)
Стек операндов
... →
..., objectref
Описание
index — это беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу index должна содержать reference. Ссылка objectref в локальной переменной по индексу index помещается на стек операндов.
Примечания
Инструкция aload не может использоваться для загрузки значения типа returnAddress из локальной переменной на стек операндов. Эта асимметрия с инструкцией astore (§astore) является намеренной.
Кодовое слово aload может быть использовано в сочетании с инструкцией wide (§wide) для доступа к локальной переменной, используя двухбайтовый беззнаковый индекс.
aload_
Операция
Загрузка reference из локальной переменной
Формат
aload_
Формы
aload_0 = 42 (0x2a)
aload_1 = 43 (0x2b)
aload_2 = 44 (0x2c)
aload_3 = 45 (0x2d)
Стек операндов
... →
..., objectref
Описание
<n> должно быть индексом в массиве локальных переменных текущей рамки (§2.6). Локальная переменная в позиции <n> должна содержать reference. objectref из локальной переменной в позиции <n> помещается в стек операндов.
Примечания
Инструкцию aload_returnAddress из локальной переменной в стек операндов. Эта асимметрия с соответствующей инструкцией astore_
Каждая из инструкций aload_
anewarray
Операция
Создать новый массив reference
Формат
anewarray
indexbyte1
indexbyte2
Формы
anewarray = 189 (0xbd)
Стек операндов
..., count →
..., arrayref
Описание
Значение count должно иметь тип int. Оно извлекается из стека операндов. Значение count представляет количество элементов создаваемого массива. Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на класс, массив или тип интерфейса. Наименованный класс, массив или тип интерфейса разрешается (§5.4.3.1). Новый массив с элементами указанного типа и длиной count выделяется из кучи с автоматическим управлением памятью, и ссылка arrayref на этот новый объект массива помещается в стек операндов. Все элементы нового массива инициализируются значением null, значением по умолчанию для типов reference (§2.4).
Исключения при связывании
При разрешении символической ссылки на класс, массив или тип интерфейса могут быть выброшены любые исключения, описанные в §5.4.3.1.
Исключения времени выполнения
В противном случае, если count меньше нуля, инструкция anewarray вызывает исключение NegativeArraySizeException.
Примечания
Инструкция anewarray используется для создания одномерного массива ссылок на объекты или части многомерного массива.
areturn
Операция
Возврат reference из метода
Формат
areturn
Формы
areturn = 176 (0xb0)
Стек операндов
..., objectref →
[пусто]
Описание
Значение objectref должно быть типа reference и должно ссылаться на объект типа, совместимого с типом, представленным возвращаемым дескриптором (§4.3.3) текущего метода. Если текущий метод является методом synchronized, монитор, вошедший или повторно вошедший при вызове метода, обновляется и, возможно, выходит, как если бы был выполнен оператор monitorexit (§monitorexit) в текущем потоке. Если исключение не выброшено, objectref извлекается из стека операндов текущей рамки (§2.6) и помещается в стек операндов рамки вызывающего метода. Все другие значения в стеке операндов текущего метода удаляются.
Затем интерпретатор восстанавливает рамку вызывающего метода и возвращает управление вызывающему методу.
Исключения во время выполнения
Если реализация Java Virtual Machine не применяет правила, относящиеся к структурированному блокированию, описанные в §2.11.10, то если текущий метод является методом synchronized, а текущий поток не является владельцем монитора, вошедшего или повторно вошедшего при вызове метода, areturn выбросит исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит оператор monitorexit, но не оператор monitorenter, для объекта, на котором синхронизирован метод.
В противном случае, если реализация Java Virtual Machine применяет правила структурированного блокирования, описанные в §2.11.10, и если первое из этих правил нарушено при вызове текущего метода, то areturn выбросит исключение IllegalMonitorStateException.
arraylength
Операция
Получить длину массива
Формат
arraylength
Формы
arraylength = 190 (0xbe)
Стек операндов
..., arrayref →
..., length
Описание
arrayref должен быть типа reference и должен ссылаться на массив. Он извлекается из стека операндов. Определяется длина (length) массива, на который он ссылается. Эта длина помещается в стек операндов как int.
Исключения во время выполнения
Если arrayref является null, инструкция arraylength вызывает исключение NullPointerException.
astore
Операция
Сохранить reference в локальную переменную
Формат
astore
index
Формы
astore = 58 (0x3a)
Стек операндов
..., objectref →
...
Описание
index — это беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей фрейма (§2.6). objectref на вершине стека операндов должен быть типа returnAddress или типа reference. Он извлекается из стека операндов, а значение локальной переменной в позиции index устанавливается в objectref.
Примечания
Инструкция astore используется с objectref типа returnAddress при реализации условия finally языка программирования Java (§3.13).
Инструкция aload (§aload) не может использоваться для загрузки значения типа returnAddress из локальной переменной в стек операндов. Эта асимметрия с инструкцией astore умышленна.
Опекод astore может использоваться совместно с инструкцией wide (§wide), чтобы получить доступ к локальной переменной, используя двухбайтовый беззнаковый индекс.
astore_
Операция
Сохранение reference в локальной переменной
Формат
astore_
Формы
astore_0 = 75 (0x4b)
astore_1 = 76 (0x4c)
astore_2 = 77 (0x4d)
astore_3 = 78 (0x4e)
Стек операндов
..., objectref →
...
Описание
<n> должно быть индексом в массиве локальных переменных текущей рамки (§2.6). objectref вверху стека операндов должно быть типа returnAddress или типа reference. Оно извлекается из стека операндов, и значение локальной переменной в позиции <n> устанавливается в objectref.
Примечания
Инструкция astore_returnAddress при реализации положений языка программирования Java, относящихся к блокам finally (§3.13).
Инструкция aload_returnAddress из локальной переменной в стек операндов. Эта асимметрия с соответствующей инструкцией astore_
Каждая из инструкций astore_
athrow
Операция
Выбросить исключение или ошибку
Формат
athrow
Формы
athrow = 191 (0xbf)
Стек операндов
..., objectref →
objectref
Описание
objectref должно быть типа reference и должно ссылаться на объект, являющийся экземпляром класса Throwable или подкласса Throwable. Оно извлекается из стека операндов. Затем objectref выбрасывается путём поиска в текущем методе (§2.6) первого обработчика исключений, соответствующего классу objectref, согласно алгоритму в §2.10.
Если обработчик исключений, соответствующий objectref, найден, он содержит расположение кода, предназначенного для обработки этого исключения. Регистр pc сбрасывается до этого расположения, стек операндов текущего кадра очищается, objectref возвращается в стек операндов, и выполнение продолжается.
Если в текущем кадре не найден соответствующий обработчик исключений, этот кадр удаляется. Если текущий кадр представляет собой вызов метода synchronized, монитор, вошедший или повторно вошедший при вызове метода, покидается как при выполнении инструкции monitorexit (§monitorexit). Наконец, кадр вызывающей программы восстанавливается, если такой кадр существует, и objectref повторно выбрасывается. Если такой кадр не существует, текущая нить завершается.
Исключения во время выполнения
Если objectref является null, athrow выбрасывает NullPointerException вместо objectref.
В противном случае, если реализация Java Virtual Machine не применяет правила структурированной блокировки, описанные в §2.11.10, то если метод текущего кадра является методом synchronized, и текущая нить не является владельцем монитора, вошедшего или повторно вошедшего при вызове метода, athrow выбрасывает IllegalMonitorStateException вместо объекта, который ранее выбрасывался. Это может произойти, например, если метод synchronized, который прерывисто завершается, содержит инструкцию monitorexit, но не инструкцию monitorenter, по объекту, на котором синхронизирован метод.
В противном случае, если реализация Java Virtual Machine применяет правила структурированной блокировки, описанные в §2.11.10, и если первое из этих правил нарушено во время вызова текущего метода, то athrow выбрасывает IllegalMonitorStateException вместо объекта, который ранее выбрасывался.
Примечания
Диаграмма стека операндов для инструкции athrow может быть вводящей в заблуждение: Если обработчик для этого исключения найден в текущем методе, инструкция athrow отбрасывает все значения в стеке операндов, затем помещает брошенный объект в стек операндов. Однако, если обработчик не найден в текущем методе и исключение выбрасывается дальше по цепочке вызова методов, тогда стек операндов метода (если таковой имеется), который обрабатывает исключение, очищается, и objectref помещается в этот пустой стек операндов. Все промежуточные кадры от метода, который бросил исключение, до метода, который обрабатывает исключение, но не включая его, удаляются.
baload
Операция
Загрузка byte или boolean из массива
Формат
baload
Формы
baload = 51 (0x33)
Стек операндов
..., arrayref, index →
..., value
Описание
arrayref должен быть типа reference и должен ссылаться на массив, компоненты которого имеют тип byte или тип boolean. index должен быть типа int. Оба arrayref и index извлекаются из стека операндов. Значение value компонента массива в позиции index извлекается, расширяется со знаком до int value и помещается на вершину стека операндов.
Исключения во время выполнения
Если arrayref является null, baload генерирует исключение NullPointerException.
В противном случае, если index не входит в пределы массива, на который ссылается arrayref, инструкция baload генерирует исключение ArrayIndexOutOfBoundsException.
Примечания
Инструкция baload используется для загрузки значений из массивов byte и boolean. В реализации виртуальной машины Java Oracle, массивы boolean — то есть массивы типа T_BOOLEAN (§2.2, §newarray) — реализуются как массивы 8-битовых значений. Другие реализации могут реализовать упакованные массивы boolean; инструкция baload таких реализаций должна использоваться для доступа к этим массивам.
bastore
Операция
Запись в массив типа byte или boolean
Формат
bastore
Формы
bastore = 84 (0x54)
Стек операндов
..., arrayref, index, value →
...
Описание
arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип byte или boolean. index и value должны оба быть типа int. arrayref, index и value извлекаются из стека операндов. Значение value усекается до типа byte и сохраняется в качестве компонента массива по индексу index.
Исключения во время выполнения
Если arrayref является null, bastore генерирует исключение NullPointerException.
В противном случае, если index выходит за пределы границ массива, ссылаемого на arrayref, инструкция bastore генерирует исключение ArrayIndexOutOfBoundsException.
Примечания
Инструкция bastore используется для записи значений в массивы типа byte и boolean. В реализации Oracle's Java Virtual Machine, массивы типа boolean (то есть массивы типа T_BOOLEAN (§2.2, §newarray)) реализуются как массивы 8-битовых значений. Другие реализации могут реализовывать упакованные массивы типа boolean; в таких реализациях инструкция bastore должна уметь записывать значения типа boolean в упакованные массивы типа boolean, а также значения типа byte в массивы типа byte.
bipush
Операция
Положить byte
Формат
bipush
byte
Формы
bipush = 16 (0x10)
Стек операндов
... →
..., value
Описание
Непосредственное значение byte расширяется со знаком до значения типа int value. Это значение value помещается на стек операндов.
caload
Операция
Загрузка char из массива
Формат
caload
Формы
caload = 52 (0x34)
Стек операндов
..., arrayref, index →
..., value
Описание
arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип char. index должен быть типа int. И arrayref, и index извлекаются из стека операндов. Компонент массива по индексу index извлекается и расширяется до беззнакового int значения value. Это значение value помещается в стек операндов.
Исключения во время выполнения
Если arrayref является null, caload генерирует исключение NullPointerException.
В противном случае, если index выходит за пределы массива, на который ссылается arrayref, инструкция caload генерирует исключение ArrayIndexOutOfBoundsException.
castore
Операция
Запись в массив char
Формат
castore
Формы
castore = 85 (0x55)
Стек операндов
..., arrayref, index, value →
...
Описание
arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип char. index и value должны быть типа int. arrayref, index, и value извлекаются из стека операндов. Значение value приводится к типу char и сохраняется как компонент массива по индексу index.
Исключения во время выполнения
Если arrayref является null, castore генерирует исключение NullPointerException.
В противном случае, если index выходит за пределы массива, на который ссылается arrayref, инструкция castore генерирует исключение ArrayIndexOutOfBoundsException.
checkcast
Операция
Проверка, является ли объект заданного типа
Формат
checkcast
indexbyte1
indexbyte2
Формы
checkcast = 192 (0xc0)
Стек операндов
..., objectref →
..., objectref
Описание
Объект objectref должен быть типа reference. Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения по этому индексу должен быть символической ссылкой на класс, массив или интерфейс.
Если objectref равен null, то стек операндов не изменяется.
В противном случае, указанный класс, массив или тип интерфейса разрешаются (§5.4.3.1). Если objectref может быть преобразован к разрешённому классу, массиву или типу интерфейса, стек операндов не изменяется; в противном случае, инструкция checkcast генерирует исключение ClassCastException.
Следующие правила используются для определения возможности преобразования objectref, который не является null, к разрешённому типу: если S — класс объекта, на который ссылается objectref, а T — разрешённый класс, массив или тип интерфейса, checkcast определяет возможность преобразования objectref к типу T следующим образом:
-
Если S — обычный (не массива) класс, то:
-
Если T — тип класса, то S должен быть тем же классом, что и T, или S должен быть подклассом T;
-
Если T — тип интерфейса, то S должен реализовывать интерфейс T.
-
-
Если S — тип интерфейса, то:
-
Если T — тип класса, то T должен быть
Object. -
Если T — тип интерфейса, то T должен быть тем же интерфейсом, что и S, или суперинтерфейсом S.
-
-
Если S — класс, представляющий тип массива SC
[], то есть массив компонентов типа SC, то:-
Если T — тип класса, то T должен быть
Object. -
Если T — тип интерфейса, то T должен быть одним из интерфейсов, реализуемых массивами (JLS §4.10.3).
-
Если T — тип массива TC
[], то есть массив компонентов типа TC, то одно из следующих условий должно быть истинным:-
TC и SC — один и тот же примитивный тип.
-
TC и SC — ссылочные типы, и тип SC может быть преобразован к TC путём рекурсивного применения этих правил.
-
-
Исключения при привязке
При разрешении символической ссылки на класс, массив или тип интерфейса может быть выброшено любое из исключений, описанных в §5.4.3.1.
Исключение времени выполнения
В противном случае, если objectref не может быть преобразован к разрешённому классу, массиву или типу интерфейса, инструкция checkcast генерирует исключение ClassCastException.
Примечания
Инструкция checkcast очень похожа на инструкцию instanceof (§instanceof). Она отличается обработкой null, поведением при неудачном тесте (инструкция checkcast генерирует исключение, instanceof помещает код результата) и влиянием на стек операндов.
d2f
Операция
Преобразовать double в float
Формат
d2f
Формы
d2f = 144 (0x90)
Стек операндов
..., значение →
..., результат
Описание
Значение значение на вершине стека операндов должно быть типа double. Оно извлекается из стека операндов и преобразуется с помощью преобразования множества значений (§2.8.3), что приводит к значение'. Затем значение' преобразуется в float результат с использованием режима округления IEEE 754 до ближайшего значения. Результат результат помещается в стек операндов.
Если инструкция d2f является FP-строгой (§2.8.2), результат преобразования всегда округляется до ближайшего представимого значения в множестве значений типа float (§2.3.2).
Если инструкция d2f не является FP-строгой, результат преобразования может быть взят из множества значений с расширенным экспонентом (§2.3.2); он не обязательно округляется до ближайшего представимого значения в множестве значений типа float.
Конечное значение' слишком маленькое для представления как float преобразуется в ноль с тем же знаком; конечное значение' слишком большое для представления как float преобразуется в бесконечность с тем же знаком. double NaN преобразуется в float NaN.
Примечания
Инструкция d2f выполняет сужающее преобразование примитивов (JLS §5.1.3). Она может потерять информацию об общем значении значение' и может также потерять точность.
d2i
Операция
Преобразовать double в int
Формат
d2i
Формы
d2i = 142 (0x8e)
Стек операндов
..., значение →
..., результат
Описание
Значение значение на вершине стека операндов должно быть типа double. Оно извлекается из стека операндов и подвергается преобразованию типов значений (§2.8.3), в результате чего получается значение'. Затем значение' преобразуется в int. Результат помещается в стек операндов:
-
Если значение' равно NaN, результат преобразования —
int0. -
В противном случае, если значение' не равно бесконечности, оно округляется до целого значения V с округлением к нулю в соответствии с режимом округления IEEE 754 к нулю. Если это целое значение V может быть представлено как
int, то результатом являетсяintзначение V. -
В противном случае, либо значение' слишком мало (отрицательное значение большой величины или минус бесконечность), и результат — наименьшее представимое значение типа
int, либо значение' слишком велико (положительное значение большой величины или плюс бесконечность), и результат — наибольшее представимое значение типаint.
Примечания
Инструкция d2i выполняет сужающее преобразование примитивных типов (JLS §5.1.3). Она может потерять информацию о общей величине значение' и может также потерять точность.
d2l
Операция
Преобразовать double в long
Формат
d2l
Формы
d2l = 143 (0x8f)
Стек операндов
..., значение →
..., результат
Описание
Значение значение на вершине стека операндов должно быть типа double. Оно извлекается из стека операндов и подвергается преобразованию в соответствии с набором значений (§2.8.3), в результате чего получается значение'. Затем значение' преобразуется в long. Результат результат помещается в стек операндов:
-
Если значение' равно NaN, то результат преобразования —
long0. -
В противном случае, если значение' не является бесконечностью, оно округляется до целого значения V, с округлением к нулю в соответствии с режимом IEEE 754 округления к нулю. Если это целое значение V может быть представлено как
long, то результат — это значениеlongV. -
В противном случае, либо значение' слишком мало (отрицательное значение большой величины или отрицательная бесконечность), и результат — наименьшее представимое значение типа
long, либо значение' слишком велико (положительное значение большой величины или положительная бесконечность), и результат — наибольшее представимое значение типаlong.
Примечания
Инструкция d2l выполняет сужающее преобразование примитивов (JLS §5.1.3). Она может потерять информацию о величине значение' и может также потерять точность.
dadd
Операция
Добавить double
Формат
dadd
Формы
dadd = 99 (0x63)
Стек операндов
..., value1, value2 →
..., результат
Описание
И value1, и value2 должны быть типа double. Значения извлекаются из стека операндов и подвергаются преобразованию типов (§2.8.3), в результате чего получаются value1' и value2'. double Результат результат равен value1' + value2'. Результат результат помещается в стек операндов.
Результат инструкции dadd регулируется правилами IEEE арифметики:
-
Если value1' или value2' равно NaN, результат равен NaN.
-
Сумма двух бесконечностей с разными знаками равна NaN.
-
Сумма двух бесконечностей с одинаковыми знаками равна бесконечности того же знака.
-
Сумма бесконечности и любого конечного значения равна бесконечности.
-
Сумма двух нулей с разными знаками равна положительному нулю.
-
Сумма двух нулей с одинаковыми знаками равна нулю того же знака.
-
Сумма нуля и ненулевого конечного значения равна ненулевому значению.
-
Сумма двух ненулевых конечных значений с одинаковым модулем и разными знаками равна положительному нулю.
-
В остальных случаях, когда ни один операнд не является бесконечностью, нулём или NaN, а значения имеют одинаковый знак или разные модули, сумма вычисляется и округляется до ближайшего представимого значения с использованием режима IEEE 754 округления до ближайшего. Если модуль слишком велик для представления как
double, мы говорим, что операция переполняет; результат затем является бесконечностью соответствующего знака. Если модуль слишком мал для представления какdouble, мы говорим, что операция переполняет; результат затем равен нулю соответствующего знака.
Виртуальная машина Java требует поддержки постепенного переполнения, как определено в IEEE 754. Несмотря на то, что может произойти переполнение, недополнение или потеря точности, выполнение инструкции dadd никогда не вызывает исключение во время выполнения.
daload
Операция
Загрузка значения из массива
Формат
daload
Формы
daload = 49 (0x31)
Стек операндов
..., arrayref, index →
..., value
Описание
arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип double. index должен быть типа int. Оба arrayref и index извлекаются из стека операндов. Значение double в компоненте массива по индексу index извлекается и помещается в стек операндов.
Исключения во время выполнения
Если arrayref является null, то daload выбрасывает исключение NullPointerException.
В противном случае, если index выходит за пределы массива, на который ссылается arrayref, то инструкция daload выбрасывает исключение ArrayIndexOutOfBoundsException.
dastore
Операция
Сохранение значения в массив
Формат
dastore
Формы
dastore = 82 (0x52)
Стек операндов
..., arrayref, index, value →
...
Описание
arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип double. index должен быть типа int, а value — типа double. arrayref, index и value извлекаются из стека операндов. Значение value претерпевает преобразование (§2.8.3), в результате чего получается value', которое сохраняется как компонент массива по индексу index.
Исключения во время выполнения
Если arrayref является null, то dastore выбрасывает исключение NullPointerException.
В противном случае, если index выходит за пределы массива, на который ссылается arrayref, то инструкция dastore выбрасывает исключение ArrayIndexOutOfBoundsException.
dcmp<op>
Операция
Сравнение double
Формат
dcmp<op>
Формы
dcmpg = 152 (0x98)
dcmpl = 151 (0x97)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба значения value1 и value2 должны быть типа double. Значения извлекаются из стека операндов и подвергаются преобразованию набора значений (§2.8.3), в результате чего получаются value1' и value2'. Производится сравнение с плавающей запятой:
-
Если value1' больше value2', на стек операндов помещается значение
int1. -
В противном случае, если value1' равно value2', на стек операндов помещается значение
int0. -
В противном случае, если value1' меньше value2', на стек операндов помещается значение
int-1. -
В противном случае, по крайней мере одно из value1' или value2' является NaN. Инструкция dcmpg помещает значение
int1 на стек операндов, а инструкция dcmpl — значениеint-1.
Сравнение с плавающей запятой выполняется в соответствии со стандартом IEEE 754. Все значения, кроме NaN, упорядочены, при этом отрицательная бесконечность меньше всех конечных значений, а положительная бесконечность больше всех конечных значений. Положительный и отрицательный нули считаются равными.
Примечания
Инструкции dcmpg и dcmpl отличаются только обработкой сравнения, включающего NaN. NaN неупорядочено, поэтому любое сравнение double терпит неудачу, если один или оба операнда являются NaN. При наличии как dcmpg, так и dcmpl, любое double сравнение может быть скомпилировано для помещения того же значения result на стек операндов, независимо от того, терпит ли неудачу сравнение по значениям, не являющимся NaN, или из-за того, что встретился NaN. Дополнительная информация содержится в §3.5.
dconst_
Операция
Положить double
Формат
dconst_
Формы
dconst_0 = 14 (0xe)
dconst_1 = 15 (0xf)
Стек операндов
... →
..., <d>
Описание
Положить константу double <d> (0.0 или 1.0) на стек операндов.
ddiv
Операция
Деление
Формат
ddiv
Формы
ddiv = 111 (0x6f)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа double. Значения извлекаются из стека операндов и преобразуются согласно правилам преобразования наборов значений (§2.8.3), что даёт значение1' и значение2'. Результат результат равен значение1' / значение2'. Результат помещается в стек операндов.
Результат инструкции ddiv регулируется правилами арифметики IEEE:
-
Если значение1' или значение2' равно NaN, результат равен NaN.
-
Если ни значение1', ни значение2' не равно NaN, знак результата положительный, если оба значения имеют одинаковый знак, отрицательный, если знаки разные.
-
Деление бесконечности на бесконечность даёт NaN.
-
Деление бесконечности на конечное значение даёт бесконечность соответствующего знака, согласно правилу определения знака.
-
Деление конечного значения на бесконечность даёт ноль соответствующего знака, согласно правилу определения знака.
-
Деление нуля на ноль даёт NaN; деление нуля на любое другое конечное значение даёт ноль соответствующего знака, согласно правилу определения знака.
-
Деление ненулевого конечного значения на ноль даёт бесконечность соответствующего знака, согласно правилу определения знака.
-
В остальных случаях, когда ни один операнд не является бесконечностью, нулём или NaN, частное вычисляется и округляется до ближайшего
doubleв режиме округления IEEE 754 до ближайшего значения. Если значение слишком велико, чтобы быть представленным какdouble, операция переполняется; результатом тогда является бесконечность соответствующего знака. Если значение слишком мало, чтобы быть представленным какdouble, операция переполняется; результатом тогда является ноль соответствующего знака.
Виртуальная машина Java требует поддержки постепенного уменьшения значения, как определено в IEEE 754. Несмотря на то, что может произойти переполнение, недополнение, деление на ноль или потеря точности, выполнение инструкции ddiv никогда не вызывает исключения во время выполнения.
dload
Операция
Загрузка double из локальной переменной
Формат
dload
index
Формы
dload = 24 (0x18)
Стек операндов
... →
..., значение
Описание
index — это беззнаковый байт. И index, и index+1 должны быть индексами в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу index должна содержать double. Значение локальной переменной по индексу index помещается в стек операндов.
Примечания
Операнд dload может использоваться совместно с инструкцией wide (§wide) для доступа к локальной переменной с помощью двухбайтового беззнакового индекса.
dload_<n>
Операция
Загрузка double из локальной переменной
Формат
dload_<n>
Формы
dload_0 = 38 (0x26)
dload_1 = 39 (0x27)
dload_2 = 40 (0x28)
dload_3 = 41 (0x29)
Стек операндов
... →
..., значение
Описание
И <n>, и <n>+1 должны быть индексами в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу <n> должна содержать double. Значение локальной переменной по индексу <n> помещается в стек операндов.
Примечания
Каждая из инструкций dload_<n> эквивалентна инструкции dload с индексом <n>, за исключением того, что операнд <n> неявный.
dmul
Операция
Умножение double
Формат
dmul
Формы
dmul = 107 (0x6b)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба value1 и value2 должны быть типа double. Значения извлекаются из стека операндов и преобразуются в соответствии с набором значений (§2.8.3), в результате чего получаются value1' и value2'. Результат double равен value1' * value2'. Результат result помещается в стек операндов.
Результат инструкции dmul регулируется правилами арифметики IEEE:
-
Если value1' или value2' равно NaN, результат равен NaN.
-
Если ни value1' ни value2' не равно NaN, знак результата положительный, если оба значения имеют одинаковый знак, и отрицательный, если знаки разные.
-
Умножение бесконечности на ноль приводит к NaN.
-
Умножение бесконечности на конечное значение приводит к знаковой бесконечности, со знаком, задаваемым указанным правилом.
-
В оставшихся случаях, когда не участвуют ни бесконечности, ни NaN, произведение вычисляется и округляется до ближайшего представимого значения с использованием режима округления IEEE 754 до ближайшего. Если значение слишком велико для представления как
double, мы говорим, что операция переполняет; результат в этом случае — бесконечность соответствующего знака. Если значение слишком мало для представления какdouble, мы говорим, что операция переполняется; результат в этом случае — ноль соответствующего знака.
Виртуальная машина Java требует поддержки постепенного переполнения, как определено в IEEE 754. Несмотря на то, что может произойти переполнение, переполнение, или потеря точности, выполнение инструкции dmul никогда не вызывает исключения во время выполнения.
dneg
Операция
Изменить знак double
Формат
dneg
Формы
dneg = 119 (0x77)
Стек операндов
..., значение →
..., результат
Описание
Значение должно быть типа double. Оно извлекается из стека операндов и преобразуется к набору значений (§2.8.3), что приводит к значению'. double результат - это арифметическое отрицание значения'. Результат помещается в стек операндов.
Для double значений отрицание не эквивалентно вычитанию из нуля. Если x - это +0.0, то 0.0-x равно +0.0, но -x равно -0.0. Унарный минус просто инвертирует знак double.
Важные частные случаи:
-
Если операнд - NaN, результат - NaN (вспомните, что NaN не имеет знака).
-
Если операнд - бесконечность, результат - бесконечность с противоположным знаком.
-
Если операнд - ноль, результат - ноль с противоположным знаком.
drem
Операция
Остаток double
Формат
drem
Формы
drem = 115 (0x73)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба значения value1 и value2 должны быть типа double. Значения извлекаются из стека операндов и преобразуются с помощью преобразования набора значений (§2.8.3), получая value1' и value2'. Результат result вычисляется и помещается в стек операндов как значение типа double.
Результат инструкции drem не совпадает с результатом так называемой операции вычисления остатка, определенной в стандарте IEEE 754. Операция вычисления остатка IEEE 754 вычисляет остаток от округленного деления, а не от усеченного, и поэтому её поведение не аналогично обычному оператору вычисления остатка для целых чисел. Вместо этого Java Virtual Machine определяет drem так, чтобы его поведение было аналогично поведению инструкций вычисления остатка для целых чисел Java Virtual Machine (irem и lrem); это можно сравнить с функцией библиотеки C fmod.
Результат инструкции drem подчиняется следующим правилам:
-
Если value1' или value2' равно NaN, результат равен NaN.
-
Если ни value1' ни value2' не равно NaN, знак результата совпадает со знаком делимого.
-
Если делимое является бесконечностью или делитель равен нулю, или оба, результат равен NaN.
-
Если делимое конечно, а делитель бесконечен, результат равен делимому.
-
Если делимое равно нулю, а делитель конечен, результат равен делимому.
-
В остальных случаях, когда ни один из операндов не является бесконечностью, нулем или NaN, остаток с плавающей точкой result от делимого value1' и делителя value2' определяется математическим соотношением result = value1' - (value2' * q), где q — целое число, которое отрицательно только тогда, когда value1' / value2' отрицательно, и положительно только тогда, когда value1' / value2' положительно, и по модулю как можно больше, не превышая по модулю истинного математического частного от value1' и value2'.
Несмотря на то, что деление на ноль может произойти, вычисление инструкции drem никогда не генерирует исключение во время выполнения. Переполнение, недополнение или потеря точности не могут произойти.
Примечания
Операция вычисления остатка IEEE 754 может быть вычислена библиотечной процедурой Math.IEEEremainder.
dreturn
Операция
Возврат double из метода
Формат
dreturn
Формы
dreturn = 175 (0xaf)
Стек операндов
..., значение →
[пусто]
Описание
Текущий метод должен иметь тип возвращаемого значения double. Значение должно быть типа double. Если текущий метод является методом synchronized, монитор, вошедший или повторно вошедший при вызове метода, обновляется и, возможно, выходит, как если бы выполнялась инструкция monitorexit (§monitorexit) в текущей нити. Если исключение не возникает, значение извлекается из стека операндов текущей рамки (§2.6) и претерпевает преобразование набора значений (§2.8.3), что приводит к значению'. Значение' помещается в стек операндов рамки вызывающей стороны. Любые другие значения в стеке операндов текущего метода удаляются.
Затем интерпретатор возвращает управление вызывающей стороне метода, восстанавливая рамку вызывающей стороны.
Исключения во время выполнения
Если реализация Java Virtual Machine не выполняет правила структурированного блокирования, описанные в §2.11.10, то если текущий метод является методом synchronized, и текущая нить не является владельцем монитора, вошедшего или повторно вошедшего при вызове метода, dreturn генерирует исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит инструкцию monitorexit, но не инструкцию monitorenter, на объекте, по которому метод синхронизирован.
В противном случае, если реализация Java Virtual Machine выполняет правила структурированного блокирования, описанные в §2.11.10, и если первое из этих правил нарушается во время вызова текущего метода, то dreturn генерирует исключение IllegalMonitorStateException.
dstore
Операция
Сохранить double в локальную переменную
Формат
dstore
индекс
Формы
dstore = 57 (0x39)
Стек операндов
..., значение →
...
Описание
Значение индекс — это беззнаковый байт. И индекс, и индекс+1 должны быть индексами в массиве локальных переменных текущей фрейма (§2.6). Значение значение вверху стека операндов должно быть типа double. Оно извлекается из стека операндов и преобразуется в значение множества (§2.8.3), в результате чего получается значение'. Локальные переменные по индексам индекс и индекс+1 устанавливаются в значение'.
Примечания
Инструкция dstore может быть использована совместно с инструкцией wide (§wide), чтобы получить доступ к локальной переменной с помощью двубайтового беззнакового индекса.
dstore_<n>
Операция
Сохранить double в локальную переменную
Формат
dstore_<n>
Формы
dstore_0 = 71 (0x47)
dstore_1 = 72 (0x48)
dstore_2 = 73 (0x49)
dstore_3 = 74 (0x4a)
Стек операндов
..., значение →
...
Описание
И <n>, и <n>+1 должны быть индексами в массиве локальных переменных текущей фрейма (§2.6). Значение значение вверху стека операндов должно быть типа double. Оно извлекается из стека операндов и преобразуется в значение множества (§2.8.3), в результате чего получается значение'. Локальные переменные по индексам <n> и <n>+1 устанавливаются в значение'.
Примечания
Каждая из инструкций dstore_<n> идентична инструкции dstore с индексом <n>, за исключением того, что операнд <n> является неявным.
dsub
Операция
Вычитание double
Формат
dsub
Формы
dsub = 103 (0x67)
Стек операндов
..., value1, value2 →
..., результат
Описание
И value1, и value2 должны быть типа double. Значения извлекаются из стека операндов и преобразуются с использованием преобразования набора значений (§2.8.3), в результате чего получаются value1' и value2'. double результат равен value1' - value2'. Полученный результат помещается в стек операндов.
Для double вычитания, всегда a-b даёт тот же результат, что и a+(-b). Однако, для инструкции dsub, вычитание из нуля не равно отрицанию, поскольку если x равно +0.0, то 0.0-x равно +0.0, но -x равно -0.0.
Виртуальная машина Java требует поддержки постепенного переполнения, как определено в IEEE 754. Несмотря на то, что может произойти переполнение, недополнение или потеря точности, выполнение инструкции dsub никогда не генерирует исключение во время выполнения.
dup
Операция
Дублирование значения вершины стека операндов
Формат
dup
Формы
dup = 89 (0x59)
Стек операндов
..., значение →
..., значение, значение
Описание
Дублирует верхнее значение в стеке операндов и помещает дублированное значение в стек операндов.
Инструкция dup не должна использоваться, если значение не является значением вычислительного типа категории 1 (§2.11.1).
dup_x1
Операция
Дублирует значение вершины стека операндов и вставляет его на две позиции вниз
Формат
dup_x1
Формы
dup_x1 = 90 (0x5a)
Стек операндов
..., value2, value1 →
..., value1, value2, value1
Описание
Дублирует значение вершины стека операндов и вставляет дублированное значение на две позиции вниз в стеке операндов.
Инструкция dup_x1 не должна использоваться, если value1 и value2 не являются значениями вычислительного типа категории 1 (§2.11.1).
dup_x2
Операция
Дублирует значение вершины стека операндов и вставляет его на две или три позиции вниз
Формат
dup_x2
Формы
dup_x2 = 91 (0x5b)
Стек операндов
Форма 1:
..., value3, value2, value1 →
..., value1, value3, value2, value1
где value1, value2 и value3 — значения вычислительного типа категории 1 (§2.11.1).
Форма 2:
..., value2, value1 →
..., value1, value2, value1
где value1 — значение вычислительного типа категории 1, а value2 — значение вычислительного типа категории 2 (§2.11.1).
Описание
Дублирует значение вершины стека операндов и вставляет дублированное значение на две или три позиции вниз в стеке операндов.
dup2
Операция
Дублирует верхнее значение или два значения из стека операндов
Формат
dup2
Формы
dup2 = 92 (0x5c)
Стек операндов
Форма 1:
..., value2, value1 →
..., value2, value1, value2, value1
где оба value1 и value2 — значения вычислительного типа категории 1 (§2.11.1).
Форма 2:
..., value →
..., value, value
где value — значение вычислительного типа категории 2 (§2.11.1).
Описание
Дублирует верхнее значение или два значения в стеке операндов и помещает дублированное значение или значения обратно в стек операндов в исходном порядке.
dup2_x1
Операция
Дублирует верхнее значение или два значения из стека операндов и вставляет эти значения на два или три позиции вниз
Формат
dup2_x1
Формы
dup2_x1 = 93 (0x5d)
Стек операндов
Форма 1:
..., value3, value2, value1 →
..., value2, value1, value3, value2, value1
где value1, value2 и value3 — значения вычислительного типа категории 1 (§2.11.1).
Форма 2:
..., value2, value1 →
..., value1, value2, value1
где value1 — значение вычислительного типа категории 2, а value2 — значение вычислительного типа категории 1 (§2.11.1).
Описание
Дублирует верхнее значение или два значения из стека операндов и вставляет дублированные значения в исходном порядке под исходным значением или значениями в стеке операндов.
dup2_x2
Операция
Дублирует верхнее или два верхних значения стека операндов и вставляет два, три или четыре значения вниз
Формат
dup2_x2
Формы
dup2_x2 = 94 (0x5e)
Стек операндов
Форма 1:
..., value4, value3, value2, value1 →
..., value2, value1, value4, value3, value2, value1
где value1, value2, value3 и value4 — значения вычислительного типа категории 1 (§2.11.1).
Форма 2:
..., value3, value2, value1 →
..., value1, value3, value2, value1
где value1 — значение вычислительного типа категории 2, а value2 и value3 — значения вычислительного типа категории 1 (§2.11.1).
Форма 3:
..., value3, value2, value1 →
..., value2, value1, value3, value2, value1
где value1 и value2 — значения вычислительного типа категории 1, а value3 — значение вычислительного типа категории 2 (§2.11.1).
Форма 4:
..., value2, value1 →
..., value1, value2, value1
где value1 и value2 — значения вычислительного типа категории 2 (§2.11.1).
Описание
Дублирует верхнее или два верхних значения в стеке операндов и вставляет дублированные значения в исходном порядке в стек операндов.
f2d
Операция
Преобразовать float в double
Формат
f2d
Формы
f2d = 141 (0x8d)
Стек операндов
..., значение →
..., результат
Описание
Значение значение на вершине стека операндов должно быть типа float. Оно извлекается из стека операндов и преобразуется с использованием преобразования набора значений (§2.8.3), в результате получается значение'. Затем значение' преобразуется в double результат. Этот результат помещается в стек операндов.
Примечания
Когда инструкция f2d является FP-строгой (§2.8.2), она выполняет расширяющее преобразование примитивного типа (JLS §5.1.2). Поскольку все значения набора значений float (§2.3.2) точно представимы значениями набора значений double (§2.3.2), такое преобразование является точным.
Если инструкция f2d не является FP-строгой, результат преобразования может быть взят из набора значений с расширенным порядком двойной точности; он не обязательно округляется до ближайшего представимого значения в наборе значений double. Однако, если операнд значение взят из набора значений с расширенным порядком одинарной точности, а целевой результат ограничен набором значений double, может потребоваться округление значение.
f2i
Операция
Преобразовать float в int
Формат
f2i
Формы
f2i = 139 (0x8b)
Стек операндов
..., значение →
..., результат
Описание
Значение значение на вершине стека операндов должно быть типа float. Оно извлекается из стека операндов и преобразуется с помощью преобразования множества значений (§2.8.3), в результате чего получается значение'. Затем значение' преобразуется в int результат. Этот результат помещается в стек операндов:
-
Если значение' равно NaN, результат преобразования —
int0. -
В противном случае, если значение' не равно бесконечности, оно округляется до целого значения V с округлением к нулю, используя режим округления IEEE 754 к нулю. Если это целое значение V может быть представлено как
int, то результат —intзначение V. -
В противном случае, либо значение' слишком мало (отрицательное значение большой величины или отрицательная бесконечность), и результат — наименьшее представимое значение типа
int, либо значение' слишком велико (положительное значение большой величины или положительная бесконечность), и результат — наибольшее представимое значение типаint.
Примечания
Инструкция f2i выполняет сужающее примитивное преобразование (JLS §5.1.3). Она может потерять информацию о величине значение' и может также потерять точность.
f2l
Операция
Преобразование float в long
Формат
f2l
Формы
f2l = 140 (0x8c)
Стек операндов
..., значение →
..., результат
Описание
Значение значение на вершине стека операндов должно быть типа float. Оно извлекается из стека операндов и преобразуется с помощью преобразования набора значений (§2.8.3), в результате чего получается значение'. Затем значение' преобразуется в long результат. Этот результат помещается в стек операндов:
-
Если значение' равно NaN, результат преобразования —
long0. -
В противном случае, если значение' не бесконечность, оно округляется до целого значения V, используя IEEE 754 режим округления к нулю. Если это целое значение V может быть представлено как
long, то результат — значениеlongV. -
В противном случае, либо значение' слишком мало (отрицательное значение большой величины или отрицательная бесконечность), и результат — наименьшее представимое значение типа
long, либо значение' слишком велико (положительное значение большой величины или положительная бесконечность), и результат — наибольшее представимое значение типаlong.
Примечания
Инструкция f2l выполняет сужающее примитивное преобразование (JLS §5.1.3). Она может потерять информацию о величине значение' и может также потерять точность.
fadd
Операция
Сложить float
Формат
fadd
Формы
fadd = 98 (0x62)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба значения value1 и value2 должны быть типа float. Эти значения извлекаются из стека операндов и подвергаются преобразованию типов (§2.8.3), в результате чего получаются value1' и value2'. Результат result вычисляется как value1' + value2'. Результат записывается в стек операндов.
Результат инструкции fadd определяется правилами арифметики IEEE:
-
Если value1' или value2' равно NaN, результат равен NaN.
-
Сумма двух бесконечностей с разными знаками равна NaN.
-
Сумма двух бесконечностей с одинаковыми знаками равна бесконечности с тем же знаком.
-
Сумма бесконечности и любого конечного значения равна бесконечности.
-
Сумма двух нулей с разными знаками равна положительному нулю.
-
Сумма двух нулей с одинаковыми знаками равна нулю с тем же знаком.
-
Сумма нуля и ненулевого конечного значения равна ненулевому значению.
-
Сумма двух ненулевых конечных значений с одинаковым модулем и разными знаками равна положительному нулю.
-
В остальных случаях, когда ни один операнд не является бесконечностью, нулём или NaN, и значения имеют одинаковый знак или разные модули, сумма вычисляется и округляется до ближайшего представимого значения с использованием режима округления IEEE 754 до ближайшего. Если модуль слишком велик для представления в виде
float, операция переполняется; результат — бесконечность соответствующего знака. Если модуль слишком мал для представления в видеfloat, операция подполняется; результат — ноль соответствующего знака.
Виртуальная машина Java требует поддержки постепенного подполения, как определено в IEEE 754. Несмотря на то, что может произойти переполнение, подполение или потеря точности, выполнение инструкции fadd никогда не вызывает исключения во время выполнения.
faload
Операция
Загрузка float из массива
Формат
faload
Формы
faload = 48 (0x30)
Стек операндов
..., arrayref, index →
..., value
Описание
Тип arrayref должен быть reference, и он должен ссылаться на массив, чьи компоненты имеют тип float. index должен быть типа int. arrayref и index извлекаются из стека операндов. Значение float в компоненте массива по индексу index извлекается и помещается на стек операндов.
Исключения во время выполнения
Если arrayref является null, faload генерирует исключение NullPointerException.
В противном случае, если index не находится в пределах границ массива, на который ссылается arrayref, инструкция faload генерирует исключение ArrayIndexOutOfBoundsException.
fastore
Операция
Запись в массив float
Формат
fastore
Формы
fastore = 81 (0x51)
Стек операндов
..., arrayref, index, value →
...
Описание
Тип arrayref должен быть reference, и он должен ссылаться на массив, чьи компоненты имеют тип float. index должен быть типа int, а value должен быть типа float. arrayref, index и value извлекаются из стека операндов. Значение value подвергается преобразованию (§2.8.3), в результате получаем value', и value' сохраняется как компонент массива по индексу index.
Исключения во время выполнения
Если arrayref является null, fastore генерирует исключение NullPointerException.
В противном случае, если index не находится в пределах границ массива, на который ссылается arrayref, инструкция fastore генерирует исключение ArrayIndexOutOfBoundsException.
fcmp<op>
Операция
Сравнение float
Формат
fcmp<op>
Формы
fcmpg = 150 (0x96)
fcmpl = 149 (0x95)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба value1 и value2 должны быть типа float. Значения извлекаются из стека операндов и подвергаются преобразованию множества значений (§2.8.3), что приводит к value1' и value2'. Выполняется сравнение с плавающей точкой:
-
Если value1' больше value2', на стек операндов помещается значение 1.
-
В противном случае, если value1' равно value2', на стек операндов помещается значение 0.
-
В противном случае, если value1' меньше value2', на стек операндов помещается значение -1.
-
В противном случае, по крайней мере одно из value1' или value2' является NaN. Инструкция fcmpg помещает на стек операндов значение 1, а инструкция fcmpl помещает значение -1.
Сравнение с плавающей точкой выполняется в соответствии с IEEE 754. Все значения, кроме NaN, упорядочены, при этом отрицательная бесконечность меньше всех конечных значений, а положительная бесконечность больше всех конечных значений. Положительный и отрицательный ноль считаются равными.
Примечания
Инструкции fcmpg и fcmpl различаются только обработкой сравнения, включающего NaN. NaN неупорядочено, поэтому любое float сравнение терпит неудачу, если один или оба его операнда являются NaN. Благодаря наличию как fcmpg, так и fcmpl, любое float сравнение может быть скомпилировано для помещения того же result на стек операндов, независимо от того, терпит ли сравнение неудачу на значениях, не являющихся NaN, или терпит неудачу из-за обнаружения NaN. Дополнительную информацию см. в §3.5.
fconst_
Операция
Положить float
Формат
fconst_
Формы
fconst_0 = 11 (0xb)
fconst_1 = 12 (0xc)
fconst_2 = 13 (0xd)
Стек операндов
... →
..., <f>
Описание
Поместить константу float <f> (0.0, 1.0 или 2.0) в стек операндов.
fdiv
Операция
Деление float
Формат
fdiv
Формы
fdiv = 110 (0x6e)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа float. Значения извлекаются из стека операндов и подвергаются преобразованию набора значений (§2.8.3), в результате чего получаются значение1' и значение2'. Полученный float результат равен значение1' / значение2'. Результат записывается в стек операндов.
Результат инструкции fdiv регулируется правилами арифметики IEEE:
-
Если значение1' или значение2' равно NaN, результат равен NaN.
-
Если ни значение1' ни значение2' не равно NaN, знак результата положительный, если оба значения имеют одинаковый знак, и отрицательный, если знаки отличаются.
-
Деление бесконечности на бесконечность дает NaN.
-
Деление бесконечности на конечное значение дает бесконечность соответствующего знака, согласно правилу определения знака.
-
Деление конечного значения на бесконечность дает нуль соответствующего знака, согласно правилу определения знака.
-
Деление нуля на нуль дает NaN; деление нуля на любое другое конечное значение дает нуль соответствующего знака, согласно правилу определения знака.
-
Деление ненулевого конечного значения на нуль дает бесконечность соответствующего знака, согласно правилу определения знака.
-
В оставшихся случаях, когда ни один операнд не является бесконечностью, нулём или NaN, частное вычисляется и округляется до ближайшего
floatс использованием режима округления IEEE 754 до ближайшего. Если величина слишком велика для представления в видеfloat, операция переполняет; результат тогда равен бесконечности соответствующего знака. Если величина слишком мала для представления в видеfloat, операция подполняет; результат тогда равен нулю соответствующего знака.
Виртуальная машина Java требует поддержки постепенного подпола, как определено в IEEE 754. Несмотря на то, что переполнение, подпополнение, деление на ноль или потеря точности могут произойти, выполнение инструкции fdiv никогда не генерирует исключение во время выполнения.
fload
Операция
Загрузка float из локальной переменной
Формат
fload
index
Формы
fload = 23 (0x17)
Стек операндов
... →
..., значение
Описание
index — это беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей фрейма (§2.6). Локальная переменная по индексу index должна содержать float. Значение локальной переменной по индексу index помещается в стек операндов.
Примечания
Операнд fload можно использовать в сочетании с инструкцией wide (§wide), чтобы получить доступ к локальной переменной с использованием двухбайтового беззнакового индекса.
fload_<n>
Операция
Загрузка float из локальной переменной
Формат
fload_<n>
Формы
fload_0 = 34 (0x22)
fload_1 = 35 (0x23)
fload_2 = 36 (0x24)
fload_3 = 37 (0x25)
Стек операндов
... →
..., значение
Описание
<n> должно быть индексом в массиве локальных переменных текущей фрейма (§2.6). Локальная переменная по индексу <n> должна содержать float. Значение локальной переменной по индексу <n> помещается в стек операндов.
Примечания
Каждая из инструкций fload_<n> аналогична инструкции fload с индексом <n>, за исключением того, что операнд <n> неявный.
fmul
Операция
Умножение float
Формат
fmul
Формы
fmul = 106 (0x6a)
Стек операндов
..., value1, value2 →
..., результат
Описание
Оба value1 и value2 должны быть типа float. Значения извлекаются из стека операндов и преобразуются (§2.8.3), что приводит к значениям value1' и value2'. Полученный float результат равен value1' * value2'. Результат помещается в стек операндов.
Результат инструкции fmul подчиняется правилам арифметики IEEE:
-
Если value1' или value2' равно NaN, результат равен NaN.
-
Если ни value1' ни value2' не равно NaN, знак результата положительный, если оба значения имеют одинаковый знак, и отрицательный, если знаки отличаются.
-
Умножение бесконечности на ноль приводит к NaN.
-
Умножение бесконечности на конечное значение приводит к бесконечности соответствующего знака, согласно правилу, указанному выше.
-
В оставшихся случаях, где не участвуют бесконечность или NaN, произведение вычисляется и округляется до ближайшего представимого значения, используя режим округления IEEE 754 до ближайшего. Если величина слишком велика для представления в качестве
float, операция переполняет; результатом является бесконечность соответствующего знака. Если величина слишком мала для представления в качествеfloat, операция недополняет; результатом является ноль соответствующего знака.
Виртуальная машина Java требует поддержки постепенного недополнения, как определено в IEEE 754. Несмотря на то, что могут произойти переполнение, недополнение или потеря точности, выполнение инструкции fmul никогда не вызывает исключения во время выполнения.
fneg
Операция
Изменить знак float
Формат
fneg
Формы
fneg = 118 (0x76)
Стек операндов
..., value →
..., result
Описание
Значение value должно быть типа float. Оно извлекается из стека операндов и претерпевает преобразование набора значений (§2.8.3), что приводит к value'. Результат result является арифметическим отрицанием value'. Этот result помещается в стек операндов.
Для значений float, отрицание не равно вычитанию из нуля. Если x есть +0.0, то 0.0-x равно +0.0, но -x равно -0.0. Унарный минус просто меняет знак float.
Особые случаи:
-
Если операнд — NaN, результат — NaN (напомним, что NaN не имеет знака).
-
Если операнд — бесконечность, результат — бесконечность противоположного знака.
-
Если операнд — ноль, результат — ноль противоположного знака.
frem
Операция
Остаток float
Формат
frem
Формы
frem = 114 (0x72)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба value1 и value2 должны быть типа float. Значения извлекаются из стека операндов и преобразуются с помощью преобразования набора значений (§2.8.3), в результате чего получаются value1' и value2'. result вычисляется и помещается в стек операндов как float.
Результат инструкции frem отличается от результата так называемой операции вычисления остатка, определённой стандартом IEEE 754. Операция вычисления остатка по IEEE 754 вычисляет остаток от округленного деления, а не от усеченного деления, поэтому её поведение не аналогично поведению обычного оператора вычисления остатка для целых чисел. Вместо этого Java Virtual Machine определяет поведение frem аналогично поведению инструкций вычисления остатка для целых чисел Java Virtual Machine (irem и lrem); это можно сравнить с функцией C-библиотеки fmod.
Результат инструкции frem регулируется следующими правилами:
-
Если value1' или value2' равно NaN, результат равен NaN.
-
Если ни value1' ни value2' не равно NaN, знак результата совпадает со знаком делимого.
-
Если делимое является бесконечностью, делитель – нулём или оба – результат равен NaN.
-
Если делимое конечно, а делитель – бесконечность, результат равен делимому.
-
Если делимое – ноль, а делитель – конечное число, результат равен делимому.
-
В остальных случаях, когда ни один операнд не является бесконечностью, нулём или NaN, остаток с плавающей точкой result от делимого value1' и делителя value2' определяется математическим соотношением result = value1' - (value2' * q), где q – целое число, отрицательное только если value1' / value2' отрицательное и положительное только если value1' / value2' положительное, и его величина максимальна, но не превышает величины истинного математического частного value1' и value2'.
Несмотря на то, что может произойти деление на ноль, вычисление инструкции frem никогда не вызывает исключение во время выполнения. Переполнение, недополнение или потеря точности не могут произойти.
Примечания
Операцию вычисления остатка по IEEE 754 можно вычислить с помощью библиотечной функции Math.IEEEremainder.
freturn
Операция
Возврат float из метода
Формат
freturn
Формы
freturn = 174 (0xae)
Стек операндов
..., value →
[пусто]
Описание
Текущий метод должен иметь тип возвращаемого значения float. Значение value должно быть типа float. Если текущий метод является методом synchronized, монитор, вошедший или повторно вошедший во время вызова метода, обновляется и, возможно, выходит, как если бы был выполнен оператор monitorexit (§monitorexit) в текущем потоке. Если исключение не возникает, value извлекается из стека операндов текущей рамки (§2.6) и претерпевает преобразование набора значений (§2.8.3), в результате чего получается value'. Значение value' помещается в стек операндов рамки вызывающего метода. Любые другие значения в стеке операндов текущего метода удаляются.
Затем интерпретатор возвращает управление вызывающему методу, восстанавливая рамку вызывающего метода.
Исключения во время выполнения
Если реализация Java Virtual Machine не проверяет правила упорядоченного блокирования, описанные в §2.11.10, то если текущий метод является методом synchronized, и текущий поток не является владельцем монитора, вошедшего или повторно вошедшего во время вызова метода, freturn генерирует исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит инструкцию monitorexit, но не monitorenter для объекта, на котором синхронизирован метод.
В противном случае, если реализация Java Virtual Machine проверяет правила упорядоченного блокирования, описанные в §2.11.10, и если первое из этих правил нарушается во время вызова текущего метода, то freturn генерирует исключение IllegalMonitorStateException.
fstore
Операция
Сохранить float в локальную переменную
Формат
fstore
index
Формы
fstore = 56 (0x38)
Стек операндов
..., value →
...
Описание
Значение index — это беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей рамки (§2.6). Значение value вверху стека операндов должно быть типа float. Оно извлекается из стека операндов и подвергается преобразованию типа (§2.8.3), в результате чего получается value'. Значение локальной переменной по индексу index устанавливается в value'.
Примечания
Операция fstore может быть использована совместно с инструкцией wide (§wide) для доступа к локальной переменной с помощью двубайтового беззнакового индекса.
fstore_<n>
Операция
Сохранить float в локальную переменную
Формат
fstore_<n>
Формы
fstore_0 = 67 (0x43)
fstore_1 = 68 (0x44)
fstore_2 = 69 (0x45)
fstore_3 = 70 (0x46)
Стек операндов
..., value →
...
Описание
<n> должен быть индексом в массиве локальных переменных текущей рамки (§2.6). Значение value на вершине стека операндов должно быть типа float. Оно извлекается из стека операндов и подвергается преобразованию типа (§2.8.3), в результате чего получается value'. Значение локальной переменной по индексу <n> устанавливается в value'.
Примечания
Каждая из инструкций fstore_<n> идентична инструкции fstore с индексом <n>, за исключением того, что операнд <n> является неявным.
fsub
Операция
Вычитание float
Формат
fsub
Формы
fsub = 102 (0x66)
Стек операндов
..., value1, value2 →
..., result
Описание
И value1, и value2 должны быть типа float. Значения извлекаются из стека операндов и подвергаются преобразованию типа значений (§2.8.3), в результате чего получаются value1' и value2'. Результирующее значение result равно value1' - value2'. Результат помещается в стек операндов.
Для вычитания float, всегда верно, что a-b даёт тот же результат, что и a+(-b). Однако для инструкции fsub вычитание из нуля не равно отрицанию, так как если x равно +0.0, то 0.0-x равно +0.0, но -x равно -0.0.
Виртуальная машина Java требует поддержки постепенного уменьшения (underflow) в соответствии с IEEE 754. Несмотря на то, что может произойти переполнение, недополнение или потеря точности, выполнение инструкции fsub никогда не вызывает исключение во время выполнения.
getfield
Операция
Извлечение поля из объекта
Формат
getfield
indexbyte1
indexbyte2
Формы
getfield = 180 (0xb4)
Стек операндов
..., objectref →
..., value
Описание
objectref, который должен быть типа reference, извлекается из стека операндов. Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на поле (§5.1), которая содержит имя и дескриптор поля, а также символическую ссылку на класс, в котором находится поле. Ссылка на поле разрешается (§5.4.3.2). Значение value указанного поля в objectref извлекается и помещается в стек операндов.
Тип objectref не должен быть типом массива. Если поле является protected (§4.6), и оно является членом суперкласса текущего класса, и поле не объявлено в том же пакете времени выполнения (§5.3), что и текущий класс, то класс objectref должен быть либо текущим классом, либо подклассом текущего класса.
Исключения связи
При разрешении символической ссылки на поле могут быть выброшены любые ошибки, относящиеся к разрешению поля (§5.4.3.2).
В противном случае, если разрешенное поле является static полем, getfield выбрасывает исключение IncompatibleClassChangeError.
Исключение во время выполнения
В противном случае, если objectref является null, инструкция getfield выбрасывает исключение NullPointerException.
Примечания
Инструкция getfield не может использоваться для доступа к полю length массива. Вместо этого используется инструкция arraylength (§arraylength).
getstatic
Операция
Получение поля static из класса
Формат
getstatic
indexbyte1
indexbyte2
Формы
getstatic = 178 (0xb2)
Стек операндов
..., →
..., значение
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на поле (§5.1), которая содержит имя и дескриптор поля, а также символическую ссылку на класс или интерфейс, в котором находится поле. Ссылка на поле разрешается (§5.4.3.2).
При успешном разрешении поля, класс или интерфейс, объявляющий разрешенное поле, инициализируются (§5.5), если этот класс или интерфейс еще не был инициализирован.
Значение поля класса или интерфейса извлекается и помещается в стек операндов.
Исключения связывания
При разрешении символической ссылки на поле класса или интерфейса могут быть выброшены любые исключения, относящиеся к разрешению поля (§5.4.3.2).
В противном случае, если разрешенное поле не является полем класса (класса) или полем интерфейса, getstatic генерирует исключение IncompatibleClassChangeError.
Исключение во время выполнения
В противном случае, если выполнение этой инструкции getstatic вызывает инициализацию ссылаемого класса или интерфейса, getstatic может сгенерировать исключение Error, как подробно описано в §5.5.
goto
Операция
Безусловный переход
Формат
goto
branchbyte1
branchbyte2
Формы
goto = 167 (0xa7)
Стек операндов
Без изменений
Описание
Незаполненные байты branchbyte1 и branchbyte2 используются для построения знакового 16-битного смещения перехода branchoffset, где branchoffset это (branchbyte1 << 8) | branchbyte2. Выполнение продолжается по этому смещению от адреса оператора данной инструкции goto. Адрес назначения должен быть адресом оператора инструкции в методе, содержащем данную инструкцию goto.
goto_w
Операция
Безусловный переход (широкий индекс)
Формат
goto_w
branchbyte1
branchbyte2
branchbyte3
branchbyte4
Формы
goto_w = 200 (0xc8)
Стек операндов
Без изменений
Описание
Незаполненные байты branchbyte1, branchbyte2, branchbyte3, и branchbyte4 используются для построения знакового 32-битного смещения перехода branchoffset, где branchoffset это (branchbyte1 << 24) | (branchbyte2 << 16) | (branchbyte3 << 8) | branchbyte4. Выполнение продолжается по этому смещению от адреса оператора данной инструкции goto_w. Адрес назначения должен быть адресом оператора инструкции в методе, содержащем данную инструкцию goto_w.
Примечания
Несмотря на то, что инструкция goto_w использует 4-байтовое смещение перехода, другие факторы ограничивают размер метода до 65535 байтов (§4.11). Это ограничение может быть увеличено в будущих версиях виртуальной машины Java.
i2b
Операция
Преобразовать int в byte
Формат
i2b
Формы
i2b = 145 (0x91)
Стек операндов
..., значение →
..., результат
Описание
Значение значение на вершине стека операндов должно быть типа int. Оно извлекается из стека операндов, усекается до byte, а затем расширяется со знаком до int результат. Этот результат помещается на стек операндов.
Примечания
Инструкция i2b выполняет сужающее преобразование примитивных типов (JLS §5.1.3). Она может потерять информацию о величине значение. Результат также может иметь другой знак, чем значение.
i2c
Операция
Преобразовать int в char
Формат
i2c
Формы
i2c = 146 (0x92)
Стек операндов
..., значение →
..., результат
Описание
Значение значение на вершине стека операндов должно быть типа int. Оно извлекается из стека операндов, усекается до char, а затем расширяется без знака до int результат. Этот результат помещается на стек операндов.
Примечания
Инструкция i2c выполняет сужающее преобразование примитивных типов (JLS §5.1.3). Она может потерять информацию о величине значение. Результат (который всегда положительный) также может иметь другой знак, чем значение.
i2d
Операция
Преобразовать int в double
Формат
i2d
Формы
i2d = 135 (0x87)
Стек операндов
..., значение →
..., результат
Описание
Значение значение на вершине стека операндов должно быть типа int. Оно извлекается из стека операндов и преобразуется в тип double результат. Результат помещается на стек операндов.
Примечания
Инструкция i2d выполняет расширяющее преобразование примитивных типов (JLS §5.1.2). Поскольку все значения типа int точно представляются типом double, преобразование является точным.
i2f
Операция
Преобразовать int в float
Формат
i2f
Формы
i2f = 134 (0x86)
Стек операндов
..., значение →
..., результат
Описание
Значение значение на вершине стека операндов должно быть типа int. Оно извлекается из стека операндов и преобразуется в тип float результат с использованием режима округления IEEE 754 до ближайшего. Результат помещается на стек операндов.
Примечания
Инструкция i2f выполняет расширяющее преобразование примитивных типов (JLS §5.1.2), но может привести к потере точности, потому что значения типа float имеют только 24 бита значащих цифр.
i2l
Операция
Преобразовать int в long
Формат
i2l
Формы
i2l = 133 (0x85)
Стек операндов
..., значение →
..., результат
Описание
Значение значение на вершине стека операндов должно быть типа int. Оно извлекается из стека операндов и расширяется со знаком до long результат. Этот результат помещается на стек операндов.
Примечания
Инструкция i2l выполняет расширяющее преобразование примитивных типов (JLS §5.1.2). Поскольку все значения типа int точно представимы типом long, преобразование является точным.
i2s
Операция
Преобразовать int в short
Формат
i2s
Формы
i2s = 147 (0x93)
Стек операндов
..., значение →
..., результат
Описание
Значение значение на вершине стека операндов должно быть типа int. Оно извлекается из стека операндов, усекается до short, затем расширяется со знаком до int результат. Этот результат помещается на стек операндов.
Примечания
Инструкция i2s выполняет сужающее преобразование примитивных типов (JLS §5.1.3). Она может потерять информацию о величине значение. Результат также может иметь другой знак, чем значение.
iadd
Операция
Сложение int
Формат
iadd
Формы
iadd = 96 (0x60)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба value1 и value2 должны быть типа int. Значения извлекаются из стека операндов. Результат result равен value1 + value2. Результат result помещается в стек операндов.
Результат представляет собой 32 младших бита истинного математического результата в достаточно широком формате дополнения до двух, представленного как значение типа int. Если происходит переполнение, то знак результата может не совпадать со знаком математической суммы двух значений.
Несмотря на то, что может произойти переполнение, выполнение инструкции iadd никогда не вызывает исключение во время выполнения.
iaload
Операция
Загрузка int из массива
Формат
iaload
Формы
iaload = 46 (0x2e)
Стек операндов
..., arrayref, index →
..., value
Описание
arrayref должен быть типа reference и должен ссылаться на массив, чьи компоненты являются типа int. index должен быть типа int. Оба arrayref и index извлекаются из стека операндов. Значение value в компоненте массива по индексу index извлекается и помещается в стек операндов.
Исключения во время выполнения
Если arrayref является null, iaload генерирует исключение NullPointerException.
В противном случае, если index не находится в пределах границ массива, на который ссылается arrayref, инструкция iaload генерирует исключение ArrayIndexOutOfBoundsException.
iand
Операция
Логическое И int
Формат
iand
Формы
iand = 126 (0x7e)
Стек операндов
..., value1, value2 →
..., результат
Описание
Оба value1 и value2 должны быть типа int. Они извлекаются из стека операндов. int результат вычисляется путём поразрядного И (конъюнкции) value1 и value2. результат помещается в стек операндов.
iastore
Операция
Запись в массив int
Формат
iastore
Формы
iastore = 79 (0x4f)
Стек операндов
..., arrayref, индекс, значение →
...
Описание
arrayref должен быть типа reference и должен ссылаться на массив, компоненты которого имеют тип int. индекс и значение должны быть типа int. arrayref, индекс и значение извлекаются из стека операндов. int значение записывается в качестве компонента массива по индексу индекс.
Исключения во время выполнения
Если arrayref является null, iastore генерирует исключение NullPointerException.
В противном случае, если индекс выходит за пределы массива, на который ссылается arrayref, инструкция iastore генерирует исключение ArrayIndexOutOfBoundsException.
iconst_
Операция
Положить int константу
Формат
iconst_
Формы
iconst_m1 = 2 (0x2)
iconst_0 = 3 (0x3)
iconst_1 = 4 (0x4)
iconst_2 = 5 (0x5)
iconst_3 = 6 (0x6)
iconst_4 = 7 (0x7)
iconst_5 = 8 (0x8)
Стек операндов
... →
..., <i>
Описание
Положить константу <i> (-1, 0, 1, 2, 3, 4 или 5) в стек операндов.
Примечания
Каждая из инструкций этой группы эквивалентна bipush <i> для соответствующего значения <i>, за исключением того, что операнд <i> неявный.
idiv
Операция
Деление
Формат
idiv
Формы
idiv = 108 (0x6c)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба значения value1 и value2 должны быть типа int. Эти значения извлекаются из стека операндов. Результат result — это значение выражения языка программирования Java value1 / value2. Результат result помещается на стек операндов.
Операция целочисленного деления округляется к нулю; то есть, частное, полученное при делении n/d, — это значение q с наибольшим модулем, удовлетворяющее условию |d · q| ≤ |n|. Кроме того, q положительно, когда |n| ≥ |d| и n и d имеют одинаковый знак, но q отрицательно, когда |n| ≥ |d| и n и d имеют разные знаки.
Есть один особый случай, который не удовлетворяет этому правилу: если делимое — это целое число с наибольшим по модулю значением для типа int, а делитель — -1, то происходит переполнение, и результат равен делимому. Несмотря на переполнение, в этом случае исключение не генерируется.
Исключение во время выполнения
Если значение делителя в операции целочисленного деления равно 0, idiv генерирует исключение ArithmeticException.
if_acmp<cond>
Операция
Переход, если reference сравнение успешно
Формат
if_acmp<cond>
branchbyte1
branchbyte2
Формы
if_acmpeq = 165 (0xa5)
if_acmpne = 166 (0xa6)
Стек операндов
..., value1, value2 →
...
Описание
Оба value1 и value2 должны быть типа reference. Оба извлекаются из стека операндов и сравниваются. Результаты сравнения следующие:
-
if_acmpeq успешно, если и только если value1 = value2
-
if_acmpne успешно, если и только если value1 ≠ value2
Если сравнение успешно, то неподписанное branchbyte1 и branchbyte2 используются для построения знакового 16-битного смещения, где смещение вычисляется как (branchbyte1 << 8) | branchbyte2. Затем выполнение продолжается в этом смещении от адреса инструкции opcode данного if_acmp<cond>. Целевой адрес должен быть адресом инструкции opcode в методе, содержащем данную инструкцию if_acmp<cond>.
В противном случае, если сравнение неуспешно, выполнение продолжается по адресу инструкции, следующей за этой инструкцией if_acmp<cond>.
if_icmp<cond>
Операция
Переход, если int сравнение успешно
Формат
if_icmp<cond>
branchbyte1
branchbyte2
Формы
if_icmpeq = 159 (0x9f)
if_icmpne = 160 (0xa0)
if_icmplt = 161 (0xa1)
if_icmpge = 162 (0xa2)
if_icmpgt = 163 (0xa3)
if_icmple = 164 (0xa4)
Стек операндов
..., value1, value2 →
...
Описание
И value1, и value2 должны быть типа int. Они оба извлекаются из стека операндов и сравниваются. Все сравнения выполняются со знаком. Результаты сравнения следующие:
-
if_icmpeq выполняется тогда и только тогда, когда value1 = value2
-
if_icmpne выполняется тогда и только тогда, когда value1 ≠ value2
-
if_icmplt выполняется тогда и только тогда, когда value1 < value2
-
if_icmple выполняется тогда и только тогда, когда value1 ≤ value2
-
if_icmpgt выполняется тогда и только тогда, когда value1 > value2
-
if_icmpge выполняется тогда и только тогда, когда value1 ≥ value2
Если сравнение успешно, то неотрицательные branchbyte1 и branchbyte2 используются для построения знакового 16-битного смещения, где смещение рассчитывается как (branchbyte1 << 8) | branchbyte2. Затем выполнение продолжается по этому смещению от адреса операционной кодовой строки этой инструкции if_icmp<cond>. Целевой адрес должен соответствовать операционной кодовой строке инструкции в методе, который содержит эту инструкцию if_icmp<cond>.
В противном случае выполнение продолжается по адресу следующей инструкции после этой инструкции if_icmp<cond>.
if<cond>
Операция
Разветвление, если int сравнение с нулём успешно
Формат
if<cond>
branchbyte1
branchbyte2
Формы
ifeq = 153 (0x99)
ifne = 154 (0x9a)
iflt = 155 (0x9b)
ifge = 156 (0x9c)
ifgt = 157 (0x9d)
ifle = 158 (0x9e)
Стек операндов
..., value →
...
Описание
Значение value должно быть типа int. Оно извлекается из стека операндов и сравнивается с нулём. Все сравнения являются знаковыми. Результаты сравнений следующие:
-
ifeq успешно, если и только если value = 0
-
ifne успешно, если и только если value ≠ 0
-
iflt успешно, если и только если value < 0
-
ifle успешно, если и только если value ≤ 0
-
ifgt успешно, если и только если value > 0
-
ifge успешно, если и только если value ≥ 0
Если сравнение успешно, то беззнаковые branchbyte1 и branchbyte2 используются для построения знакового 16-битного смещения, где смещение вычисляется как (branchbyte1 << 8) | branchbyte2. Затем выполнение продолжается по смещению от адреса оператора данной инструкции if<cond>. Целевой адрес должен быть адресом оператора инструкции внутри метода, содержащего эту инструкцию if<cond>.
В противном случае выполнение продолжается по адресу инструкции, следующей за инструкцией if<cond>.
ifnonnull
Операция
Ветвление, если reference не null
Формат
ifnonnull
branchbyte1
branchbyte2
Формы
ifnonnull = 199 (0xc7)
Стек операндов
..., value →
...
Описание
value должно быть типа reference. Оно извлекается из стека операндов. Если value не null, то беззнаковые branchbyte1 и branchbyte2 используются для построения 16-битного знакового смещения, где смещение вычисляется как (branchbyte1 << 8) | branchbyte2. Выполнение продолжается по смещению относительно адреса операционного кода этой инструкции ifnonnull. Целевой адрес должен быть адресом операционного кода инструкции в методе, содержащем эту инструкцию ifnonnull.
В противном случае выполнение продолжается по адресу инструкции, следующей за этой инструкцией ifnonnull.
ifnull
Операция
Ветвление, если reference равно null
Формат
ifnull
branchbyte1
branchbyte2
Формы
ifnull = 198 (0xc6)
Стек операндов
..., value →
...
Описание
value должно быть типа reference. Оно извлекается из стека операндов. Если value равно null, то беззнаковые branchbyte1 и branchbyte2 используются для построения 16-битного знакового смещения, где смещение вычисляется как (branchbyte1 << 8) | branchbyte2. Выполнение продолжается по смещению относительно адреса операционного кода этой инструкции ifnull. Целевой адрес должен быть адресом операционного кода инструкции в методе, содержащем эту инструкцию ifnull.
В противном случае выполнение продолжается по адресу инструкции, следующей за этой инструкцией ifnull.
iinc
Операция
Инкрементировать локальную переменную на константу
Формат
iinc
index
const
Формы
iinc = 132 (0x84)
Стек операндов
Без изменений
Описание
index — это беззнаковый байт, который должен быть индексом в массив локальных переменных текущей рамки (§2.6). const — это непосредственный знаковый байт. Локальная переменная по индексу index должна содержать int. Сначала значение const расширяется со знаком до int, а затем локальная переменная по индексу index увеличивается на это значение.
Примечания
Операцию iinc можно использовать совместно с инструкцией wide (§wide), чтобы получить доступ к локальной переменной с помощью двубайтового беззнакового индекса и увеличить её на двубайтовое знаковое значение.
iload
Операция
Загрузить int из локальной переменной
Формат
iload
index
Формы
iload = 21 (0x15)
Стек операндов
... →
..., значение
Описание
index — это беззнаковый байт, который должен быть индексом в массив локальных переменных текущей рамки (§2.6). Локальная переменная по индексу index должна содержать int. Значение значение локальной переменной по индексу index помещается на стек операндов.
Примечания
Операцию iload можно использовать совместно с инструкцией wide (§wide) для доступа к локальной переменной с помощью двубайтового беззнакового индекса.
iload_
Операция
Загрузка int из локальной переменной
Формат
iload_
Формы
iload_0 = 26 (0x1a)
iload_1 = 27 (0x1b)
iload_2 = 28 (0x1c)
iload_3 = 29 (0x1d)
Стек операндов
... →
..., значение
Описание
<n> должно быть индексом в массиве локальных переменных текущей области видимости (§2.6). Локальная переменная в позиции <n> должна содержать int. Значение локальной переменной в позиции <n> помещается в стек операндов.
Примечания
Каждая из инструкций iload_
imul
Операция
Умножение int
Формат
imul
Формы
imul = 104 (0x68)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
И значение1, и значение2 должны быть типа int. Значения извлекаются из стека операндов. Результат результат вычисляется как значение1 * значение2. Результат помещается в стек операндов.
Результат — 32 младших бита истинного математического результата в формате с двумя дополнениями достаточной ширины, представленного как значение типа int. При переполнении знак результата может не совпадать со знаком математической суммы двух значений.
Несмотря на то, что переполнение может произойти, выполнение инструкции imul никогда не вызывает исключение во время выполнения.
ineg
Операция
Изменить знак int
Формат
ineg
Формы
ineg = 116 (0x74)
Стек операндов
..., значение →
..., результат
Описание
Значение должно быть типа int. Оно извлекается из стека операндов. int Результат — арифметическое отрицание значения, -значение. Результат помещается в стек операндов.
Для значений int, отрицание равно вычитанию из нуля. Так как Java Virtual Machine использует дополнительный код для представления целых чисел, а диапазон значений дополнительного кода не симметричен, отрицание максимального отрицательного int результата даёт это же максимальное отрицательное число. Несмотря на то, что произошло переполнение, исключение не генерируется.
Для всех int значений x, -x равно (~x)+1.
instanceof
Операция
Определяет, является ли объект данного типа
Формат
instanceof
indexbyte1
indexbyte2
Формы
instanceof = 193 (0xc1)
Стек операндов
..., objectref →
..., результат
Описание
Объект objectref, тип которого должен быть reference, извлекается из стека операндов. Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения по этому индексу должен быть символической ссылкой на тип класса, массива или интерфейса.
Если objectref равен null, то инструкция instanceof помещает значение int result равное 0 в качестве int в стек операндов.
В противном случае, указанный тип класса, массива или интерфейса разрешается (§5.4.3.1). Если objectref является экземпляром разрешённого класса или массива или реализует разрешённый интерфейс, инструкция instanceof помещает значение int result равное 1 в качестве int в стек операндов; в противном случае, помещает значение int result равное 0.
Следующие правила используются для определения того, является ли objectref, который не является null, экземпляром разрешённого типа: Если S — класс объекта, на который ссылается objectref, а T — разрешённый тип класса, массива или интерфейса, instanceof определяет, является ли objectref экземпляром T следующим образом:
-
Если S — обычный (не массива) класс, то:
-
Если T — тип класса, то S должен быть таким же классом, как T, или S должен быть подклассом T;
-
Если T — тип интерфейса, то S должен реализовывать интерфейс T.
-
-
Если S — тип интерфейса, то:
-
Если T — тип класса, то T должен быть
Object. -
Если T — тип интерфейса, то T должен быть тем же интерфейсом, что и S, или над-интерфейсом S.
-
-
Если S — класс, представляющий тип массива SC
[], то есть массив компонентов типа SC, то:-
Если T — тип класса, то T должен быть
Object. -
Если T — тип интерфейса, то T должен быть одним из интерфейсов, реализуемых массивами (JLS §4.10.3).
-
Если T — тип массива TC
[], то есть массив компонентов типа TC, то одно из следующих утверждений должно быть истинным:-
TC и SC — один и тот же примитивный тип.
-
TC и SC — типы ссылок, и тип SC может быть преобразован к TC по этим правилам времени выполнения.
-
-
Исключения при связывании
При разрешении символической ссылки на класс, массив или тип интерфейса могут быть выброшены любые исключения, описанные в §5.4.3.1.
Примечания
Инструкция instanceof очень похожа на инструкцию checkcast (§checkcast). Она отличается обработкой null, поведением при неудачном тесте (инструкция checkcast генерирует исключение, instanceof помещает код результата), а также своим влиянием на стек операндов.
invokedynamic
Операция
Вызов динамического метода
Формат
invokedynamic
indexbyte1
indexbyte2
0
0
Формы
invokedynamic = 186 (0xba)
Стек операндов
..., [arg1, [arg2 ...]] →
...
Описание
Каждое конкретное лексическое вхождение инструкции invokedynamic называется динамической точкой вызова.
Сначала неподписанные indexbyte1 и indexbyte2 используются для построения индекса в пул постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения в этом индексе должен быть символической ссылкой на спецификатор точки вызова (§5.1). Значения третьего и четвертого байтов операнда должны всегда быть нулевыми.
Спецификатор точки вызова разрешается (§5.4.3.6) для этой конкретной динамической точки вызова, чтобы получить reference к экземпляру java.lang.invoke.MethodHandle, reference к экземпляру java.lang.invoke.MethodType и reference к статическим аргументам.
Далее, в рамках продолжающегося разрешения спецификатора точки вызова, метод загрузки вызывается так, как если бы он выполнялся инструкцией invokevirtual (§invokevirtual), содержащей индекс пула постоянных времени выполнения на символическую ссылку на метод (§5.1) со следующими свойствами:
-
Имя метода равно
invoke; -
Описание метода имеет возвращаемый тип
java.lang.invoke.CallSite; -
Описание метода имеет типы параметров, полученные из элементов, помещённых в стек операндов, следующим образом.
Первые четыре типа параметров в описании —
java.lang.invoke.MethodHandle,java.lang.invoke.MethodHandles.Lookup,Stringиjava.lang.invoke.MethodTypeв указанном порядке.Если у спецификатора точки вызова есть статические аргументы, то для каждого аргумента добавляется тип параметра к типам параметров описания метода в том порядке, в котором аргументы были помещены в стек операндов. Эти типы параметров могут быть
Class,java.lang.invoke.MethodHandle,java.lang.invoke.MethodType,String,int,long,floatилиdouble. -
Символическая ссылка метода на класс, в котором должен находиться метод, указывает на класс
java.lang.invoke.MethodHandle.
при этом как будто следующие элементы, в порядке следования, помещаются в стек операндов:
-
referenceна объектjava.lang.invoke.MethodHandleдля метода загрузки; -
referenceна объектjava.lang.invoke.MethodHandles.Lookupдля класса, в котором происходит данная динамическая точка вызова; -
referenceнаStringдля имени метода в спецификаторе точки вызова; -
referenceна объектjava.lang.invoke.MethodType, полученный для описания метода в спецификаторе точки вызова; -
referenceдля классов, типов методов, хэндлов методов и строковых литералов, обозначенных как статические аргументы в спецификаторе точки вызова, а также числовых значений (§2.3.1, §2.3.2), обозначенных как статические аргументы в спецификаторе точки вызова, в порядке их появления в спецификаторе точки вызова. (То есть, для примитивных значений упаковка не происходит.)
До тех пор, пока метод загрузки может быть правильно вызван методом invoke, его описание произвольно. Например, первый тип параметра мог бы быть Object вместо java.lang.invoke.MethodHandles.Lookup, а тип возвращаемого значения — также Object вместо java.lang.invoke.CallSite.
Если метод загрузки является методом переменной арности, то некоторые или все аргументы в стеке операндов, указанные выше, могут быть объединены в массив параметров.
Вызов метода загрузки происходит в потоке, который пытается разрешить символическую ссылку на спецификатор точки вызова этой динамической точки вызова. Если таких потоков несколько, метод загрузки может быть вызван в нескольких потоках одновременно. Поэтому методы загрузки, которые обращаются к глобальным данным приложения, должны принимать обычные меры предосторожности против гонок.
Результат, возвращаемый методом bootstrap, должен быть ссылкой на объект, класс которого является java.lang.invoke.CallSite или подклассом java.lang.invoke.CallSite. Этот объект известен как объект сайта вызова. reference извлекается из стека операндов, как если бы выполнялась инструкция invokevirtual.
Если несколько потоков одновременно выполняют метод bootstrap для одного и того же динамического сайта вызова, виртуальная машина Java должна выбрать один объект сайта вызова и установить его видимым для всех потоков. Любые другие методы bootstrap, выполняемые для динамического сайта вызова, могут завершиться, но их результаты игнорируются, и выполнение динамического сайта вызова в потоках продолжается с выбранным объектом сайта вызова.
Объект сайта вызова имеет описатель типа (экземпляр java.lang.invoke.MethodType), который должен быть семантически равен объекту java.lang.invoke.MethodType, полученному для описателя метода в спецификаторе сайта вызова.
Результат успешного разрешения спецификатора сайта вызова — это объект сайта вызова, который постоянно связан с динамическим сайтом вызова.
Метод, представленный целевым объектом связанного сайта вызова, вызывается. Вызов происходит как если бы выполнялась инструкция invokevirtual (§invokevirtual), указывающая индекс пула констант времени выполнения на символическую ссылку на метод (§5.1) со следующими свойствами:
-
Имя метода —
invokeExact; -
Описатель метода — описатель метода в спецификаторе сайта вызова; и
-
Символическая ссылка метода на класс, в котором находится метод, указывает на класс
java.lang.invoke.MethodHandle.
Стек операндов будет интерпретироваться как содержащий ссылку на цель объекта сайта вызова, за которой следуют nargs значений аргументов, где количество, тип и порядок значений должны соответствовать описателю метода в спецификаторе сайта вызова.
Исключения при связывании
Если при разрешении символической ссылки на спецификатор сайта вызова возникает исключение E, инструкция invokedynamic генерирует исключение BootstrapMethodError, которое оборачивает E.
В противном случае, во время дальнейшего разрешения спецификатора сайта вызова, если вызов метода bootstrap завершается прерывисто (§2.6.5) из-за генерации исключения E, инструкция invokedynamic генерирует исключение BootstrapMethodError, которое оборачивает E. (Это может произойти, если у метода bootstrap неправильная арность, тип параметра или тип возвращаемого значения, что приводит к java.lang.invoke.MethodHandle . invoke генерировать java.lang.invoke.WrongMethodTypeException.)
В противном случае, во время дальнейшего разрешения спецификатора сайта вызова, если результат вызова метода bootstrap не является ссылкой на экземпляр java.lang.invoke.CallSite, инструкция invokedynamic генерирует исключение BootstrapMethodError.
В противном случае, во время дальнейшего разрешения спецификатора сайта вызова, если описатель типа цели объекта сайта вызова не семантически равен описателю метода в спецификаторе сайта вызова, инструкция invokedynamic генерирует исключение BootstrapMethodError.
Исключения во время выполнения
Если данный динамический сайт вызова завершил разрешение своего спецификатора сайта вызова, это означает, что ссылка на экземпляр java.lang.invoke.CallSite привязана к этому динамическому сайту вызова. Поэтому элемент стека операндов, представляющий ссылку на цель объекта сайта вызова, никогда не null. Аналогично, это означает, что описатель метода в спецификаторе сайта вызова семантически равен описателю типа обработчика метода для вызова, как если бы выполнялась инструкция invokevirtual.
Эти инварианты означают, что инструкция invokedynamic, связанная с объектом сайта вызова, никогда не генерирует исключение NullPointerException или java.lang.invoke.WrongMethodTypeException.
invokeinterface
Операция
Вызов метода интерфейса
Формат
invokeinterface
indexbyte1
indexbyte2
count
0
Формы
invokeinterface = 185 (0xb9)
Стек операндов
..., objectref, [arg1, [arg2 ...]] →
...
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле постоянных данных текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных данных по этому индексу должен быть символической ссылкой на интерфейсный метод (§5.1), который содержит имя и описание (§4.3.3) интерфейсного метода, а также символическую ссылку на интерфейс, в котором находится интерфейсный метод. Имя интерфейсного метода разрешается (§5.4.3.4). Разрешенный интерфейсный метод не должен быть методом инициализации экземпляра (§2.9) или методом инициализации класса или интерфейса (§2.9).
Операнд count — это беззнаковый байт, который не должен быть равен нулю. objectref должен быть типа reference и должен быть после него на стеке операндов nargs значений аргументов, где количество, тип и порядок значений должны соответствовать описанию разрешённого интерфейсного метода. Четвёртый байт-операнд всегда должен быть равен нулю.
Пусть C — класс objectref. Фактический вызываемый метод выбирается следующей процедурой поиска:
-
Если C содержит объявление экземплярного метода с тем же именем и описанием, что и разрешенный метод, то это метод, который должен быть вызван, и процедура поиска завершается.
-
В противном случае, если у C есть суперкласс, эта процедура поиска выполняется рекурсивно с использованием непосредственного суперкласса C; метод, который будет вызван, — результат рекурсивного вызова этой процедуры поиска.
-
В противном случае, генерируется
AbstractMethodError.
Если метод является synchronized, монитор, связанный с objectref, вводится или повторно вводится так, как если бы выполнялась инструкция monitorenter (§monitorenter) в текущей нити.
Если метод не является native, nargs значений аргументов и objectref удаляются со стека операндов. Для вызываемого метода создаётся новый фрейм в стеке виртуальной машины Java. objectref и значения аргументов последовательно становятся значениями локальных переменных нового фрейма, при этом objectref в локальной переменной 0, arg1 в локальной переменной 1 (или, если arg1 имеет тип long или double, в локальных переменных 1 и 2), и так далее. Любое значение аргумента, которое имеет тип с плавающей запятой, претерпевает преобразование множества значений (§2.8.3) перед сохранением в локальной переменной. Новый фрейм затем становится текущим, и виртуальная машина Java устанавливает значение счётчика команд (PC) на код первой инструкции вызываемого метода. Выполнение продолжается с первой инструкции метода.
Если метод является native, и зависящая от платформы реализация не была ещё связана (§5.6) с виртуальной машиной Java, то это делается. Значения аргументов nargs и objectref извлекаются из стека операндов и передаются в качестве параметров реализующему коду метода. Любое значение аргумента, являющееся типом с плавающей запятой, претерпевает преобразование множества значений (§2.8.3) перед передачей в качестве параметра. Параметры передаются, и код вызывается способом, зависящим от реализации. Когда код на платформенно-зависимом языке возвращается:
-
Если метод
nativeявляетсяsynchronized, монитор, связанный с objectref, обновляется и, возможно, выходит, как если бы выполнялась инструкция monitorexit (§monitorexit) в текущем потоке. -
Если метод
nativeвозвращает значение, возвращаемое значение зависимой от платформы кода преобразуется зависимым от реализации способом в тип возвращаемого значения методаnativeи помещается в стек операндов.
Исключения при связывании
При разрешении символической ссылки на интерфейсный метод могут быть выброшены любые исключения, относящиеся к разрешению интерфейсных методов (§5.4.3.4).
Исключения во время выполнения
В противном случае, если objectref является null, инструкция invokeinterface выбрасывает исключение NullPointerException.
В противном случае, если класс objectref не реализует разрешенный интерфейс, инструкция invokeinterface выбрасывает исключение IncompatibleClassChangeError.
В противном случае, если не выбран ни один метод, соответствующий разрешенному имени и дескриптору, инструкция invokeinterface выбрасывает исключение AbstractMethodError.
В противном случае, если выбранный метод не является public, инструкция invokeinterface выбрасывает исключение IllegalAccessError.
В противном случае, если выбранный метод является abstract, инструкция invokeinterface выбрасывает исключение AbstractMethodError.
В противном случае, если выбранный метод является native и код, реализующий метод, не может быть привязан, инструкция invokeinterface выбрасывает исключение UnsatisfiedLinkError.
Примечания
Операнд count инструкции invokeinterface записывает меру количества аргументных значений, где аргументное значение типа long или типа double вносит два единицы в значение count, а аргумент любого другого типа вносит одну единицу. Эта информация также может быть получена из дескриптора выбранного метода. Избыточность имеет историческое происхождение.
Четвёртый байт операнда существует для резервирования места для дополнительного операнда, используемого в некоторых реализациях Oracle Java Virtual Machine, которые заменяют инструкцию invokeinterface специализированной псевдоинструкцией во время выполнения. Он должен быть сохранён для обратной совместимости.
Значения аргументов nargs и objectref не находятся в однозначном соответствии с первыми nargs+1 локальными переменными. Аргументные значения типов long и double должны храниться в двух последовательных локальных переменных, поэтому для передачи nargs аргументных значений вызванному методу может потребоваться больше, чем nargs локальных переменных.
invokespecial
Операция
Вызов метода экземпляра; специальная обработка вызовов методов суперкласса, приватных и методов инициализации экземпляра
Формат
invokespecial
indexbyte1
indexbyte2
Формы
invokespecial = 183 (0xb7)
Стек операндов
..., objectref, [arg1, [arg2 ...]] →
...
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пул констант времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула констант времени выполнения по этому индексу должен быть символической ссылкой на метод (§5.1), который задаёт имя и дескриптор (§4.3.3) метода, а также символическую ссылку на класс, в котором находится метод. Имя метода разрешается (§5.4.3.3). Наконец, если разрешённый метод является protected (§4.6), является членом суперкласса текущего класса и метод не объявлен в том же пакете времени выполнения (§5.3), что и текущий класс, то класс objectref должен быть либо текущим классом, либо подклассом текущего класса.
Далее, разрешённый метод выбирается для вызова, если не выполняются все следующие условия:
-
Флаг
ACC_SUPER(Таблица 4.1) установлен для текущего класса. -
Класс разрешённого метода является суперклассом текущего класса.
-
Разрешённый метод не является методом инициализации экземпляра (§2.9).
Если вышеуказанные условия выполнены, фактический вызываемый метод выбирается с помощью следующей процедуры поиска. Пусть C является непосредственным суперклассом текущего класса:
-
Если C содержит объявление для экземпляра метода с тем же именем и дескриптором, что и разрешённый метод, то вызывается этот метод. Процедура поиска завершается.
-
В противном случае, если у C есть суперкласс, эта процедура поиска выполняется рекурсивно, используя непосредственный суперкласс C. Метод, который необходимо вызвать, является результатом рекурсивного вызова этой процедуры поиска.
-
В противном случае, возникает
AbstractMethodError.
Тип objectref должен быть reference и ему должны следовать на стеке операндов nargs аргументных значений, где количество, тип и порядок значений должны соответствовать дескриптору выбранного экземпляра метода.
Если метод является synchronized, монитор, связанный с objectref, входит или повторно входит, как если бы он выполнялся инструкцией monitorenter (§monitorenter) в текущем потоке.
Если метод не является native, nargs аргументных значений и objectref извлекаются из стека операндов. Для вызываемого метода создаётся новый кадр на стеке виртуальной машины Java. objectref и аргументные значения последовательно становятся значениями локальных переменных нового кадра, где objectref находится в локальной переменной 0, arg1 в локальной переменной 1 (или, если arg1 имеет тип long или double, в локальных переменных 1 и 2) и так далее. Любое аргументное значение с плавающей точкой претерпевает преобразование набора значений (§2.8.3) перед тем, как быть сохранённым в локальной переменной. Затем новый кадр становится текущим, и виртуальная машина Java устанавливает pc на код первой инструкции вызываемого метода. Выполнение продолжается с первой инструкции метода.
Если метод является native, и зависимый от платформы код, который его реализует, ещё не привязан (§5.6) к виртуальной машине Java, то это делается. Значения аргумента nargs и objectref извлекаются из стека операндов и передаются в качестве параметров коду, реализующему метод. Любое значение аргумента, которое является плавающей точкой, подвергается преобразованию набора значений (§2.8.3) перед тем, как передаваться в качестве параметра. Параметры передаются, и код вызывается зависящим от реализации способом. Когда зависимый от платформы код возвращает значение, происходит следующее:
-
Если метод
nativeявляетсяsynchronized, монитор, связанный с objectref, обновляется и, возможно, завершается, как будто выполняется инструкция monitorexit (§monitorexit) в текущем потоке. -
Если метод
nativeвозвращает значение, возвращаемое значение зависимого от платформы кода преобразуется зависящим от реализации способом в тип возврата методаnativeи помещается в стек операндов.
Исключения при связывании
Во время разрешения символической ссылки на метод может быть вызвано любое из исключений, относящихся к разрешению метода (§5.4.3.3).
В противном случае, если разрешённый метод является методом инициализации экземпляра, и класс, в котором он объявлен, не является классом, символически ссылающимся на инструкцию, возникает NoSuchMethodError.
В противном случае, если разрешённый метод является методом класса (static), инструкция invokespecial генерирует IncompatibleClassChangeError.
Исключения во время выполнения
В противном случае, если objectref является null, инструкция invokespecial генерирует исключение NullPointerException.
В противном случае, если ни один метод, соответствующий разрешённому имени и описанию, не выбран, invokespecial генерирует AbstractMethodError.
В противном случае, если выбранный метод является abstract, invokespecial генерирует AbstractMethodError.
В противном случае, если выбранный метод является native и код, который реализует метод, не может быть привязан, invokespecial генерирует исключение UnsatisfiedLinkError.
Примечания
Различие между инструкцией invokespecial и инструкцией invokevirtual (§invokevirtual) состоит в том, что invokevirtual вызывает метод, основанный на классе объекта. Инструкция invokespecial используется для вызова методов инициализации экземпляров (§2.9), а также private методов и методов суперкласса текущего класса.
Инструкция invokespecial называлась invokenonvirtual до выпуска JDK 1.0.2.
Значения аргумента nargs и objectref не соответствуют локальным переменным с индексами от 0 до nargs. Значения аргументов типов long и double должны храниться в двух последовательных локальных переменных, поэтому для передачи nargs значений аргументов вызываемому методу может потребоваться больше, чем nargs локальных переменных.
invokestatic
Операция
Вызов метода класса (static)
Формат
invokestatic
indexbyte1
indexbyte2
Формы
invokestatic = 184 (0xb8)
Стек операндов
..., [arg1, [arg2 ...]] →
...
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения по этому индексу должен быть символической ссылкой на метод (§5.1), который указывает имя и дескриптор (§4.3.3) метода, а также символическую ссылку на класс, в котором находится метод. Названный метод разрешается (§5.4.3.3). Разрешённый метод не должен быть методом инициализации экземпляра (§2.9) или методом инициализации класса или интерфейса (§2.9). Он должен быть static, и поэтому не может быть abstract.
При успешном разрешении метода класс, объявивший разрешенный метод, инициализируется (§5.5), если этот класс ещё не был инициализирован.
Стек операндов должен содержать nargs значений аргументов, где количество, тип и порядок значений должны соответствовать дескриптору разрешенного метода.
Если метод является synchronized, монитор, связанный с разрешенным Class объектом, входит или повторно входит, как если бы выполнялась инструкция monitorenter (§monitorenter) в текущем потоке.
Если метод не является native, nargs значений аргументов извлекаются из стека операндов. На стеке виртуальной машины Java создается новый кадр для вызываемого метода. nargs значений аргументов последовательно становятся значениями локальных переменных нового кадра, с arg1 в локальной переменной 0 (или, если arg1 типа long или double, в локальных переменных 0 и 1) и так далее. Любое значение аргумента, которое является типа с плавающей точкой, проходит преобразование набора значений (§2.8.3) перед сохранением в локальной переменной. Затем новый кадр становится текущим, и виртуальная машина Java устанавливает pc в код первой инструкции вызываемого метода. Выполнение продолжается с первой инструкции метода.
Если метод является native, а зависимая от платформы реализация его ещё не привязана (§5.6) к виртуальной машине Java, это выполняется. nargs значений аргументов извлекаются из стека операндов и передаются в качестве параметров коду, реализующему метод. Любое значение аргумента, которое является типа с плавающей точкой, проходит преобразование набора значений (§2.8.3) перед передачей в качестве параметра. Параметры передаются, и код вызывается способом, зависящим от реализации. Когда зависимый от платформы код возвращает значение, происходят следующие действия:
-
Если метод
nativeявляетсяsynchronized, монитор, связанный с разрешеннымClassобъектом, обновляется и, возможно, выходит, как если бы выполнялась инструкция monitorexit (§monitorexit) в текущем потоке. -
Если метод
nativeвозвращает значение, возвращаемое значение кода, зависимого от платформы, преобразуется способом, зависящим от реализации, в тип возврата методаnativeи помещается в стек операндов.
Исключения при связывании
При разрешении символической ссылки на метод могут быть выброшены любые исключения, связанные с разрешением метода (§5.4.3.3).
В противном случае, если разрешенный метод является методом экземпляра, инструкция invokestatic выбрасывает исключение IncompatibleClassChangeError.
Исключения времени выполнения
В противном случае, если выполнение этой инструкции invokestatic вызывает инициализацию ссылаемого класса, invokestatic может выбросить исключение Error, как подробно описано в §5.5.
В противном случае, если разрешенный метод является native, и код, реализующий метод, не может быть связан, invokestatic выбросит исключение UnsatisfiedLinkError.
Примечания
Значения аргумента nargs не соответствуют взаимно первому nargs локальным переменным. Значения аргументов типов long и double должны храниться в двух последовательных локальных переменных, поэтому для передачи nargs значений аргументов вызываемому методу может потребоваться больше, чем nargs локальных переменных.
invokevirtual
Операция
Вызов экземпляра метода; диспетчеризация на основе класса
Формат
invokevirtual
indexbyte1
indexbyte2
Формы
invokevirtual = 182 (0xb6)
Стек операндов
..., objectref, [arg1, [arg2 ...]] →
...
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на метод (§5.1), который предоставляет имя и дескриптор (§4.3.3) метода, а также символическую ссылку на класс, в котором находится метод. Имя метода разрешается (§5.4.3.3). Разрешенный метод не должен быть методом инициализации экземпляра (§2.9) или методом инициализации класса или интерфейса (§2.9). Наконец, если разрешенный метод является protected (§4.6), и он является членом суперкласса текущего класса, и метод не объявлен в той же среде выполнения (§5.3) , что и текущий класс, то класс objectref должен быть либо текущим классом, либо подклассом текущего класса.
Если разрешенный метод не является полиморфным по сигнатуре (§2.9), то инструкция invokevirtual выполняется следующим образом.
Пусть C — класс objectref. Фактический вызываемый метод выбирается с помощью следующей процедуры поиска:
-
Если C содержит объявление экземпляра метода
m, который переопределяет (§5.4.5) разрешенный метод, тоmявляется вызываемым методом, и процедура поиска завершается. -
В противном случае, если C имеет суперкласс, эта же процедура поиска выполняется рекурсивно с использованием непосредственного суперкласса C; вызываемым методом является результат рекурсивного вызова этой процедуры поиска.
-
В противном случае генерируется
AbstractMethodError.
objectref должен следовать на стеке операндов nargs значениями аргументов, где количество, тип и порядок значений должны соответствовать дескриптору выбранного экземпляра метода.
Если метод является synchronized, монитор, связанный с objectref, входит или повторно входит, как если бы выполнялась инструкция monitorenter (§monitorenter) в текущем потоке.
Если метод не является native, nargs значений аргументов и objectref извлекаются из стека операндов. Для вызываемого метода создается новый фрейм в стеке виртуальной машины Java. objectref и значения аргументов последовательно становятся значениями локальных переменных нового фрейма, при этом objectref находится в локальной переменной 0, arg1 — в локальной переменной 1 (или, если arg1 имеет тип long или double, в локальных переменных 1 и 2) и так далее. Любое значение аргумента, являющееся типом с плавающей точкой, претерпевает преобразование набора значений (§2.8.3) перед сохранением в локальной переменной. Затем новый фрейм становится текущим, а виртуальная машина Java pc устанавливается на код первой инструкции вызываемого метода. Выполнение продолжается с первой инструкции метода.
Если метод является native и зависимый от платформы код, который его реализует, ещё не привязан (§5.6) к виртуальной машине Java, то это выполняется. Значения аргументов nargs и objectref извлекаются из стека операндов и передаются в качестве параметров коду, реализующему метод. Любое значение аргумента, которое имеет тип с плавающей точкой, проходит преобразование набора значений (§2.8.3) перед тем, как передаваться в качестве параметра. Параметры передаются, и код вызывается способом, зависящим от реализации. Когда код, зависимый от платформы, возвращает значение, происходит следующее:
-
Если метод
nativeявляетсяsynchronized, монитор, связанный с objectref, обновляется и, возможно, завершается, как если бы выполнялась инструкция monitorexit (§monitorexit) в текущем потоке. -
Если метод
nativeвозвращает значение, возвращаемое значение кода, зависимого от платформы, преобразуется способом, зависящим от реализации, в тип возвращаемого значения методаnativeи помещается в стек операндов.
Если разрешённый метод является полиморфным по сигнатуре (§2.9), то инструкция invokevirtual выполняется следующим образом.
Сначала reference экземпляра java.lang.invoke.MethodType получает так, как если бы разрешалась символическая ссылка на тип метода (§5.4.3.5) с теми же типами параметров и возвращаемых значений, что и дескриптор метода, на который ссылается инструкция invokevirtual.
-
Если метод с указанным именем является
invokeExact, экземплярjava.lang.invoke.MethodTypeдолжен быть семантически равен дескриптору типа получателя дескриптора метода objectref. Обрабатываемый дескриптор метода — это objectref. -
Если метод с указанным именем является
invoke, а экземплярjava.lang.invoke.MethodTypeсемантически равен дескриптору типа получателя дескриптора метода objectref, то обрабатываемый дескриптор метода — это objectref. -
Если метод с указанным именем является
invoke, и экземплярjava.lang.invoke.MethodTypeне семантически равен дескриптору типа получателя дескриптора метода objectref, то виртуальная машина Java пытается скорректировать дескриптор типа получателя дескриптора метода, как если бы был вызванjava.lang.invoke.MethodHandle.asType, чтобы получить точно вызываемый дескриптор методаm. Обрабатываемый дескриптор метода — этоm.
objectref должен следовать в стеке операндов nargs значениями аргументов, где количество, тип и порядок значений должны быть согласованы с дескриптором типа обрабатываемого дескриптора метода. (Этот дескриптор типа будет соответствовать дескриптору метода, подходящему для типа обрабатываемого дескриптора метода, как указано в §5.4.3.5.)
Затем, если обрабатываемый дескриптор метода имеет байт-код поведение, виртуальная машина Java вызывает дескриптор метода как если бы выполнялся байт-код поведение, связанное с типом дескриптора. Если тип равен 5 (REF_invokeVirtual), 6 (REF_invokeStatic), 7 (REF_invokeSpecial), 8 (REF_newInvokeSpecial) или 9 (REF_invokeInterface), то будет создан и сделан текущим фрейм во время выполнения байт-кода поведения; когда метод, вызванный байт-кодом поведения, завершается (нормально или неожиданно), фрейм вызывающего его фрейма рассматривается как фрейм для метода, содержащего эту инструкцию invokevirtual.
Фрейм, в котором выполняется сам байт-код поведение, не виден.
В противном случае, если обрабатываемый дескриптор метода не имеет байт-кода поведения, виртуальная машина Java вызывает его способом, зависящим от реализации.
Исключения при связывании
При разрешении символической ссылки на метод могут быть сгенерированы любые исключения, относящиеся к разрешению методов (§5.4.3.3).
В противном случае, если разрешённый метод является методом класса (static), инструкция invokevirtual генерирует исключение IncompatibleClassChangeError.
В противном случае, если разрешённый метод является полиморфным по сигнатуре, то при разрешении типа метода, полученного из описателя в символической ссылке на метод, могут быть сгенерированы любые исключения, относящиеся к разрешению типа метода (§5.4.3.5).
Исключения во время выполнения
В противном случае, если objectref является null, инструкция invokevirtual генерирует исключение NullPointerException.
В противном случае, если разрешённый метод не является полиморфным по сигнатуре:
-
Если метод, соответствующий разрешённому имени и описателю, не выбран, invokevirtual генерирует исключение
AbstractMethodError. -
В противном случае, если выбранный метод является
abstract, invokevirtual генерирует исключениеAbstractMethodError. -
В противном случае, если выбранный метод является
nativeи код, реализующий метод, не может быть привязан, invokevirtual генерирует исключениеUnsatisfiedLinkError.
В противном случае, если разрешённый метод является полиморфным по сигнатуре:
-
Если имя метода является
invokeExact, и полученный экземплярjava.lang.invoke.MethodTypeне семантически равен описателю типа получающего метода-обработчика, инструкция invokevirtual генерирует исключениеjava.lang.invoke.WrongMethodTypeException. -
Если имя метода является
invoke, и полученный экземплярjava.lang.invoke.MethodTypeне является допустимым аргументом для методаjava.lang.invoke.MethodHandle.asType, вызываемого на получающем метод-обработчике, инструкция invokevirtual генерирует исключениеjava.lang.invoke.WrongMethodTypeException.
Примечания
Значения аргумента nargs и objectref не являются взаимно однозначным соответствием с первыми nargs+1 локальными переменными. Значения аргументов типов long и double должны храниться в двух последовательных локальных переменных, поэтому для передачи nargs значений аргументов вызываемому методу может потребоваться больше, чем nargs локальных переменных.
ior
Операция
Побитовое ИЛИ
Формат
ior
Формы
ior = 128 (0x80)
Стек операндов
..., value1, value2 →
..., result
Описание
И value1, и value2 должны быть типа int. Они извлекаются из стека операндов. Вычисляется результат result путём побитового включительно ИЛИ value1 и value2. Результат result помещается на стек операндов.
irem
Операция
Остаток от деления int
Формат
irem
Формы
irem = 112 (0x70)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба value1 и value2 должны быть типа int. Значения извлекаются из стека операндов. Результат result — это value1 - (value1 / value2) * value2. Результат result помещается в стек операндов.
Результат инструкции irem таков, что int равно (a/b)*b + (a%b). Это равенство выполняется даже в том частном случае, когда делимое является отрицательным a максимального возможного значения для своего типа, а делитель равен -1 (остаток равен 0). Из этого правила следует, что результат операции остатка может быть отрицательным только если делимое отрицательное и может быть положительным только если делимое положительное. Кроме того, величина результата всегда меньше величины делителя.
Исключение во время выполнения
Если значение делителя для операции остатка от деления int равно 0, irem вызывает исключение int.
ireturn
Операция
Возврат int из метода
Формат
ireturn
Формы
ireturn = 172 (0xac)
Стек операндов
..., значение →
[пустой]
Описание
Текущий метод должен иметь тип возвращаемого значения boolean, byte, short, char или int. Значение должно быть типа int. Если текущий метод является методом synchronized, монитор, вошедший или повторно вошедший при вызове метода, обновляется и, возможно, выходит так, как будто выполняется инструкция monitorexit (§monitorexit) в текущей потоке. Если исключение не возникает, значение извлекается из стека операндов текущей рамки (§2.6) и помещается в стек операндов рамки вызывающего метода. Любые другие значения в стеке операндов текущего метода удаляются.
Затем интерпретатор возвращает управление вызывающему методу, восстанавливая рамку вызывающего метода.
Исключения во время выполнения
Если реализация Java Virtual Machine не соблюдает правила структурированного блокирования, описанные в §2.11.10, то если текущий метод является методом synchronized, а текущий поток не является владельцем монитора, вошедшего или повторно вошедшего при вызове метода, ireturn генерирует исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит инструкцию monitorexit, но не инструкцию monitorenter, для объекта, на котором синхронизирован метод.
В противном случае, если реализация Java Virtual Machine соблюдает правила структурированного блокирования, описанные в §2.11.10, и если первое из этих правил нарушено во время вызова текущего метода, тогда ireturn генерирует исключение IllegalMonitorStateException.
ishl
Операция
Сдвиг влево int
Формат
ishl
Формы
ishl = 120 (0x78)
Стек операндов
..., value1, value2 →
..., result
Описание
И value1, и value2 должны быть типа int. Значения извлекаются из стека операндов. Вычисляется result путём сдвига value1 влево на s разрядов, где s — значение младших 5 битов value2. result помещается в стек операндов.
Примечания
Это эквивалентно (даже при переполнении) умножению на 2 в степени s. Расстояние сдвига, фактически используемое, всегда находится в диапазоне от 0 до 31 включительно, как если бы value2 было подвергнуто побитовому логическому И с маской 0x1f.
ishr
Операция
Арифметический сдвиг вправо int
Формат
ishr
Формы
ishr = 122 (0x7a)
Стек операндов
..., value1, value2 →
..., result
Описание
И value1, и value2 должны быть типа int. Значения извлекаются из стека операндов. Вычисляется result путём сдвига value1 вправо на s разрядов с расширением знака, где s — значение младших 5 битов value2. result помещается в стек операндов.
Примечания
Результирующее значение равно ⌊ value1 / 2s ⌋, где s — value2 & 0x1f. Для неотрицательного value1 это эквивалентно усечению int деления на 2 в степени s. Расстояние сдвига, фактически используемое, всегда находится в диапазоне от 0 до 31 включительно, как если бы value2 было подвергнуто побитовому логическому И с маской 0x1f.
istore
Операция
Сохранить int в локальную переменную
Формат
istore
индекс
Формы
istore = 54 (0x36)
Стек операндов
..., значение →
...
Описание
Индекс — это беззнаковый байт, который должен быть индексом в массив локальных переменных текущей рамки (§2.6). Значение на вершине стека операндов должно быть типа int. Оно извлекается из стека операндов, а значение локальной переменной по индексу устанавливается в значение.
Примечания
Операция istore может быть использована совместно с инструкцией wide (§wide), чтобы получить доступ к локальной переменной с помощью двубайтного беззнакового индекса.
istore_<n>
Операция
Сохранить int в локальную переменную
Формат
istore_<n>
Формы
istore_0 = 59 (0x3b)
istore_1 = 60 (0x3c)
istore_2 = 61 (0x3d)
istore_3 = 62 (0x3e)
Стек операндов
..., значение →
...
Описание
<n> должен быть индексом в массив локальных переменных текущей рамки (§2.6). Значение на вершине стека операндов должно быть типа int. Оно извлекается из стека операндов, а значение локальной переменной по <n> устанавливается в значение.
Примечания
Каждая из инструкций istore_<n> идентична инструкции istore с индексом <n>, за исключением того, что операнд <n> неявный.
isub
Операция
Вычитание int
Формат
isub
Формы
isub = 100 (0x64)
Стек операндов
..., value1, value2 →
..., результат
Описание
Оба значения value1 и value2 должны быть типа int. Значения извлекаются из стека операндов. Результат результат вычисляется как value1 - value2. Результат результат помещается в стек операндов.
Для вычитания int, a-b даёт тот же результат, что и a+(-b). Для int значений, вычитание из нуля эквивалентно взятию отрицания.
Результат представляет собой 32 младших бита истинного математического результата в достаточно широком формате со знаком дополнения до двух, представленного как значение типа int. Если произойдёт переполнение, то знак результата может не совпадать со знаком математической разницы двух значений.
Несмотря на то, что может произойти переполнение, выполнение инструкции isub никогда не вызывает исключение во время выполнения.
iushr
Операция
Логическое правое сдвиг int
Формат
iushr
Формы
iushr = 124 (0x7c)
Стек операндов
..., value1, value2 →
..., результат
Описание
Оба value1 и value2 должны быть типа int. Значения извлекаются из стека операндов. Результат результат рассчитывается путем сдвига value1 вправо на s позиций бита с расширением нуля, где s — значение 5 младших битов value2. Результат результат помещается в стек операндов.
Примечания
Если value1 положительно, а s — value2 & 0x1f, результат совпадает с результатом value1 >> s; если value1 отрицательно, результат равен значению выражения (value1 >> s) + (2 << ~s). Сложение члена (2 << ~s) компенсирует распространяемый знаковый бит. Расстояние сдвига, фактически используемое, всегда находится в диапазоне от 0 до 31 включительно.
ixor
Операция
Булево XOR int
Формат
ixor
Формы
ixor = 130 (0x82)
Стек операндов
..., value1, value2 →
..., результат
Описание
Оба value1 и value2 должны быть типа int. Они извлекаются из стека операндов. int результат вычисляется, взяв побитовое исключающее ИЛИ от value1 и value2. результат помещается в стек операндов.
jsr
Операция
Переход к подпрограмме
Формат
jsr
branchbyte1
branchbyte2
Формы
jsr = 168 (0xa8)
Стек операндов
... →
..., адрес
Описание
Адрес инструкции, следующей сразу за этой инструкцией jsr, помещается в стек операндов в качестве значения типа returnAddress. Неотрицательные branchbyte1 и branchbyte2 используются для построения знакового 16-битного смещения, где смещение равно (branchbyte1 << 8) | branchbyte2. Выполнение продолжается по адресу, смещённому на это смещение от адреса этой инструкции jsr. Целевой адрес должен соответствовать коду операции инструкции внутри метода, содержащего эту инструкцию jsr.
Примечания
Обратите внимание, что jsr помещает адрес в стек операндов, а ret (§ret) извлекает его из локальной переменной. Эта асимметрия является преднамеренной.
В реализации Oracle компилятора языка программирования Java до Java SE 6 инструкция jsr использовалась с инструкцией ret в реализации блока finally (§3.13, §4.10.2.5).
jsr_w
Операция
Подпрограмма перехода (широкий индекс)
Формат
jsr_w
branchbyte1
branchbyte2
branchbyte3
branchbyte4
Формы
jsr_w = 201 (0xc9)
Стек операндов
... →
..., адрес
Описание
Адрес (opcode) инструкции, следующей непосредственно за инструкцией jsr_w, помещается в стек операндов как значение типа returnAddress. Беззнаковые branchbyte1, branchbyte2, branchbyte3 и branchbyte4 используются для построения 32-битного смещения со знаком, где смещение равно (branchbyte1 << 24) | (branchbyte2 << 16) | (branchbyte3 << 8) | branchbyte4. Выполнение продолжается по смещению от адреса инструкции jsr_w. Адрес назначения должен соответствовать адресу opcode инструкции внутри метода, содержащего инструкцию jsr_w.
Примечания
Обратите внимание, что jsr_w помещает адрес в стек операндов, а ret (§ret) извлекает его из локальной переменной. Эта асимметрия является преднамеренной.
В реализации компилятора Oracle для языка программирования Java до Java SE 6 инструкция jsr_w использовалась с инструкцией ret в реализации условия finally (§3.13, §4.10.2.5).
Хотя инструкция jsr_w использует 4-байтовое смещение перехода, другие факторы ограничивают размер метода до 65535 байт (§4.11). Это ограничение может быть увеличено в будущих версиях виртуальной машины Java.
l2d
Операция
Преобразовать long в double
Формат
l2d
Формы
l2d = 138 (0x8a)
Стек операндов
..., значение →
..., результат
Описание
Значение значение вверху стека операндов должно быть типа long. Оно извлекается из стека операндов и преобразуется в результат типа double с использованием режима округления IEEE 754 до ближайшего. Результат помещается в стек операндов.
Примечания
Инструкция l2d выполняет расширяющее преобразование примитивного типа (JLS §5.1.2), которое может привести к потере точности, так как значения типа double имеют только 53 бита значащей части.
l2f
Операция
Преобразовать long в float
Формат
l2f
Формы
l2f = 137 (0x89)
Стек операндов
..., значение →
..., результат
Описание
Значение значение вверху стека операндов должно быть типа long. Оно извлекается из стека операндов и преобразуется в результат типа float с использованием режима округления IEEE 754 до ближайшего. Результат помещается в стек операндов.
Примечания
Инструкция l2f выполняет расширяющее преобразование примитивного типа (JLS §5.1.2), которое может привести к потере точности, так как значения типа float имеют только 24 бита значащей части.
l2i
Операция
Преобразовать long в int
Формат
l2i
Формы
l2i = 136 (0x88)
Стек операндов
..., значение →
..., результат
Описание
Значение значение на вершине стека операндов должно быть типа long. Оно извлекается из стека операндов и преобразуется в int результат путем взятия 32 младших бит значения long и отбрасывания 32 старших битов. Значение результат помещается в стек операндов.
Примечания
Инструкция l2i выполняет сужающее примитивное преобразование (JLS §5.1.3). Она может потерять информацию о величине значение. Результат также может иметь другой знак, чем значение.
ladd
Операция
Сложить long
Формат
ladd
Формы
ladd = 97 (0x61)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа long. Значения извлекаются из стека операндов. Результат результат равен значение1 + значение2.
Результат является 64 младшими битами истинного математического результата в достаточно широком формате со знаком, представленном как значение типа long. Если происходит переполнение, знак результата может не совпадать со знаком математической суммы двух значений.
Несмотря на то, что может произойти переполнение, выполнение инструкции ladd никогда не генерирует исключения во время выполнения.
laload
Операция
Загрузка long из массива
Формат
laload
Формы
laload = 47 (0x2f)
Стек операндов
..., arrayref, index →
..., value
Описание
arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип long. index должен быть типа int. Оба arrayref и index извлекаются из стека операндов. Извлекается значение value из компонента массива по индексу index и помещается в стек операндов.
Исключения во время выполнения
Если arrayref является null, laload генерирует исключение NullPointerException.
В противном случае, если index выходит за пределы массива, на который ссылается arrayref, инструкция laload генерирует исключение ArrayIndexOutOfBoundsException.
land
Операция
Логическое И long
Формат
land
Формы
land = 127 (0x7f)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба value1 и value2 должны быть типа long. Они извлекаются из стека операндов. Вычисляется результат result путём побитового И value1 и value2. result помещается в стек операндов.
lastore
Операция
Сохранение в массив long
Формат
lastore
Формы
lastore = 80 (0x50)
Стек операндов
..., arrayref, index, value →
...
Описание
arrayref должен быть типа reference и должен ссылаться на массив, компоненты которого имеют тип long. index должен быть типа int, а value – типа long. arrayref, index и value извлекаются из стека операндов. Значение value сохраняется в качестве компонента массива с индексом index.
Исключения во время выполнения
Если arrayref является null, то lastore генерирует исключение NullPointerException.
В противном случае, если index выходит за пределы массива, на который ссылается arrayref, инструкция lastore генерирует исключение ArrayIndexOutOfBoundsException.
lcmp
Операция
Сравнение long
Формат
lcmp
Формы
lcmp = 148 (0x94)
Стек операндов
..., value1, value2 →
..., result
Описание
И value1, и value2 должны быть типа long. Они оба извлекаются из стека операндов, и выполняется сравнение целых чисел со знаком. Если value1 больше value2, на стек операндов помещается значение 1. Если value1 равно value2, на стек операндов помещается значение 0. Если value1 меньше value2, на стек операндов помещается значение -1.
lconst_
Операция
Положить константу long
Формат
lconst_
Формы
lconst_0 = 9 (0x9)
lconst_1 = 10 (0xa)
Стек операндов
... →
..., <l>
Описание
Положить константу long <l> (0 или 1) на стек операндов.
ldc
Операция
Положить элемент из пула констант времени выполнения
Формат
ldc
индекс
Формы
ldc = 18 (0x12)
Стек операндов
... →
..., значение
Описание
Значение индекс — это беззнаковое байтовое значение, которое должно быть допустимым индексом в пуле констант времени выполнения текущего класса (§2.6). Элемент пула констант времени выполнения по индексу должен быть константой времени выполнения типа int или float, или символической ссылкой на строковую литерал, или символической ссылкой на класс, метод, тип метода или обработчик метода (§5.1).
Если элемент пула констант времени выполнения — это константа времени выполнения типа int или float, то числовое значение этой константы помещается в стек операндов как int или float соответственно.
В противном случае, если элемент пула констант времени выполнения — это символическая ссылка на экземпляр класса String, представляющего строковую литерал (§5.1), то ссылка на этот экземпляр, значение, помещается в стек операндов.
В противном случае, если элемент пула констант времени выполнения — это символическая ссылка на класс (§5.1), то указанный класс разрешается (§5.4.3.1) и ссылка на объект, представляющий этот класс, значение, помещается в стек операндов.
В противном случае, элемент пула констант времени выполнения должен быть символической ссылкой на тип метода или обработчик метода (§5.1). Тип метода или обработчик метода разрешаются (§5.4.3.5) и ссылка на полученный экземпляр java.lang.invoke.MethodType или java.lang.invoke.MethodHandle, значение, помещается в стек операндов.
Исключения связывания
При разрешении символической ссылки на класс может быть возбуждено любое из исключений, связанных с разрешением класса (§5.4.3.1).
При разрешении символической ссылки на тип метода или обработчик метода может быть возбуждено любое из исключений, связанных с разрешением типа метода или обработчика метода (§5.4.3.5).
ldc_w
Операция
Помещает элемент из пула констант во время выполнения (индекс с расширенным значением)
Формат
ldc_w
indexbyte1
indexbyte2
Формы
ldc_w = 19 (0x13)
Стек операндов
... →
..., значение
Описание
Беззнаковые indexbyte1 и indexbyte2 собираются в беззнаковый 16-битный индекс в пул констант во время выполнения текущего класса (§2.6), где значение индекса вычисляется как (indexbyte1 << 8) | indexbyte2. Индекс должен быть корректным индексом в пуле констант текущего класса. Элемент пула констант по этому индексу должен быть константой типа int или float, или ссылкой на строковый литерал, или символической ссылкой на класс, метод, тип метода или дескриптор метода (§5.1).
Если элемент пула констант — константа типа int или float, числовое значение этой константы помещается в стек операндов как int или float, соответственно.
В противном случае, если элемент пула констант — ссылка на экземпляр класса String, представляющего строковый литерал (§5.1), то ссылка на этот экземпляр, значение, помещается в стек операндов.
В противном случае, если элемент пула констант — символическая ссылка на класс (§4.4.1). Наименованный класс разрешается (§5.4.3.1) и ссылка на объект, представляющий этот класс, значение, помещается в стек операндов.
В противном случае, элемент пула констант должен быть символической ссылкой на тип метода или дескриптор метода (§5.1). Тип метода или дескриптор метода разрешается (§5.4.3.5) и ссылка на полученный экземпляр java.lang.invoke.MethodType или java.lang.invoke.MethodHandle, значение, помещается в стек операндов.
Исключения при линковге
Во время разрешения символической ссылки на класс могут быть выброшены любые исключения, связанные с разрешением класса (§5.4.3.1).
Во время разрешения символической ссылки на тип метода или дескриптор метода могут быть выброшены любые исключения, связанные с разрешением типа метода или дескриптора метода (§5.4.3.5).
Примечания
Инструкция ldc_w идентична инструкции ldc (§ldc), за исключением более широкого индекса пула констант во время выполнения.
Инструкция ldc_w может быть использована только для помещения значения типа float, взятого из множества значений типа float (§2.3.2), так как константа типа float в пуле констант (§4.4.4) должна быть взята из множества значений типа float.
ldc2_w
Операция
Поместить long или double из пула постоянных значений во время выполнения (индекс с расширенным диапазоном)
Формат
ldc2_w
indexbyte1
indexbyte2
Формы
ldc2_w = 20 (0x14)
Стек операндов
... →
..., значение
Описание
Беззнаковые indexbyte1 и indexbyte2 собираются в 16-битный беззнаковый индекс в пул постоянных значений текущего класса (§2.6), где значение индекса вычисляется как (indexbyte1 << 8) | indexbyte2. Индекс должен быть допустимым индексом в пуле постоянных значений текущего класса. Элемент пула постоянных значений по указанному индексу должен быть постоянной величиной типа long или double (§5.1). Численное значение этой постоянной помещается в стек операндов как long или double соответственно.
Примечания
Существует только форма инструкции ldc2_w с расширенным индексом; нет инструкции ldc2, которая помещает long или double с однобайтовым индексом.
Инструкция ldc2_w может использоваться только для помещения значения типа double из набора значений типа double (§2.3.2), так как константа типа double в пуле постоянных значений (§4.4.5) должна быть из набора значений типа double.
ldiv
Операция
Деление
Формат
ldiv
Формы
ldiv = 109 (0x6d)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа long. Значения извлекаются из стека операндов. Результат результат — это значение выражения языка программирования Java значение1 / значение2. Результат результат помещается в стек операндов.
Деление округляется до нуля; то есть, частное, полученное для long значений в n / d — это long значение q, модуль которого как можно больше, при условии |d · q| ≤ |n|. Кроме того, q положительно, когда |n| ≥ |d| и n и d имеют одинаковый знак, но q отрицательно, когда |n| ≥ |d| и n и d имеют разные знаки.
Существует один особый случай, который не удовлетворяет этому правилу: если делимое — это целое отрицательное число с наибольшим возможным модулем для типа long, а делитель — -1, то происходит переполнение, и результат равен делимому; несмотря на переполнение, исключение в этом случае не выбрасывается.
Исключение во время выполнения
Если значение делителя при делении long равно 0, ldiv выбрасывает исключение ArithmeticException.
lload
Операция
Загрузка long из локальной переменной
Формат
lload
index
Формы
lload = 22 (0x16)
Стек операндов
... →
..., значение
Описание
index — это беззнаковый байт. И index, и index+1 должны быть индексами в массиве локальных переменных текущей фрейма (§2.6). Локальная переменная по индексу index должна содержать long. Значение локальной переменной по индексу index помещается на стек операндов.
Примечания
Операция lload может быть использована совместно с инструкцией wide (§wide) для доступа к локальной переменной с помощью двубайтового беззнакового индекса.
lload_<n>
Операция
Загрузка long из локальной переменной
Формат
lload_<n>
Формы
lload_0 = 30 (0x1e)
lload_1 = 31 (0x1f)
lload_2 = 32 (0x20)
lload_3 = 33 (0x21)
Стек операндов
... →
..., значение
Описание
И <n>, и <n>+1 должны быть индексами в массиве локальных переменных текущей фрейма (§2.6). Локальная переменная по индексу <n> должна содержать long. Значение локальной переменной по индексу <n> помещается на стек операндов.
Примечания
Каждая из инструкций lload_<n> аналогична lload с индексом <n>, за исключением того, что операнд <n> неявный.
lmul
Операция
Умножение long
Формат
lmul
Формы
lmul = 105 (0x69)
Стек операндов
..., value1, value2 →
..., result
Описание
И value1, и value2 должны быть типа long. Значения извлекаются из стека операндов. Результат result равен value1 * value2. Результат result помещается в стек операндов.
Результат — 64 младших бита истинного математического результата в формате с дополнением до двух достаточной ширины, представленный как значение типа long. При переполнении знак результата может не совпадать со знаком математической суммы двух значений.
Несмотря на то, что переполнение может произойти, выполнение инструкции lmul никогда не генерирует исключение во время выполнения.
lneg
Операция
Изменение знака long
Формат
lneg
Формы
lneg = 117 (0x75)
Стек операндов
..., value →
..., result
Описание
value должно быть типа long. Оно извлекается из стека операндов. Результат result — арифметическое отрицание value, -value. Результат result помещается в стек операндов.
Для значений long, отрицание — то же, что и вычитание из нуля. Поскольку Java Virtual Machine использует представление целых чисел с дополнением до двух, а диапазон значений с дополнением до двух несимметричен, отрицание максимального отрицательного числа long приводит к тому же максимальному отрицательному числу. Несмотря на то, что переполнение произошло, исключение не генерируется.
Для всех значений long, x, -x равно (~x)+1.
lookupswitch
Операция
Доступ к таблице переходов по совпадению ключа и переход
Формат
lookupswitch
<0-3 байтовый заполнитель>
defaultbyte1
defaultbyte2
defaultbyte3
defaultbyte4
npairs1
npairs2
npairs3
npairs4
пары match-offset...
Формы
lookupswitch = 171 (0xab)
Стек операндов
..., ключ →
...
Описание
Инструкция lookupswitch имеет переменную длину. Непосредственно после кода операции lookupswitch от нуля до трёх байтов должны быть заполнителем, таким образом, чтобы defaultbyte1 начинался по адресу, кратно четырём байтам от начала текущего метода (кода первой инструкции). Непосредственно после заполнителя следуют ряд знаковых 32-битных значений: default, npairs, а затем npairs пар знаковых 32-битных значений. npairs должно быть больше или равно 0. Каждая из пар npairs состоит из int match и знакового 32-битного offset. Каждое из этих знаковых 32-битных значений создаётся из четырёх беззнаковых байтов как (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4.
Таблица пар match-offset инструкции lookupswitch должна быть отсортирована по возрастанию match.
Ключ должен быть типа int и извлекается из стека операндов. Ключ сравнивается со значениями match. Если он равен одному из них, то адрес назначения вычисляется путем добавления соответствующего offset к адресу кода операции этой инструкции lookupswitch. Если ключ не совпадает ни с одним из значений match, то адрес назначения вычисляется путём добавления default к адресу кода операции этой инструкции lookupswitch. Выполнение затем продолжается по адресу назначения.
Адрес назначения, который может быть вычислен из offset каждой пары match-offset, а также вычисленный из default, должен быть адресом кода операции инструкции внутри метода, который содержит эту инструкцию lookupswitch.
Примечания
Требуемое выравнивание 4-байтовых операндов инструкции lookupswitch гарантирует 4-байтовое выравнивание этих операндов тогда и только тогда, когда метод, который содержит lookupswitch, расположен на 4-байтовой границе.
Пары match-offset отсортированы для поддержки процедур поиска, которые быстрее, чем линейный поиск.
lor
Операция
Побитовое ИЛИ long
Формат
lor
Формы
lor = 129 (0x81)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба значения value1 и value2 должны быть типа long. Они извлекаются из стека операндов. Вычисляется значение result путём побитового включительно ИЛИ value1 и value2. Значение result помещается в стек операндов.
lrem
Операция
Остаток от деления long
Формат
lrem
Формы
lrem = 113 (0x71)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба значения value1 и value2 должны быть типа long. Значения извлекаются из стека операндов. Результат result вычисляется как value1 - (value1 / value2) * value2. Результат result помещается в стек операндов.
Результат инструкции lrem таков, что (a/b)*b + (a%b) равно a. Это тождество выполняется и в том частном случае, когда делимое является отрицательным long наибольшего возможного значения для своего типа, а делитель равен -1 (остаток равен 0). Из этого правила следует, что результат операции остатка может быть отрицательным только если делимое отрицательное, и может быть положительным только если делимое положительное; кроме того, величина результата всегда меньше величины делителя.
Исключение во время выполнения
Если значение делителя для long операции вычисления остатка равно 0, инструкция lrem генерирует исключение ArithmeticException.
lreturn
Операция
Возврат long из метода
Формат
lreturn
Формы
lreturn = 173 (0xad)
Стек операндов
..., значение →
[пустой]
Описание
Текущий метод должен иметь тип возвращаемого значения long. Значение значение должно быть типа long. Если текущий метод является методом synchronized, монитор, вошедший или повторно вошедший при вызове метода, обновляется и, возможно, завершается так, как если бы выполнялась инструкция monitorexit (§monitorexit) в текущем потоке. Если исключение не выбрасывается, значение извлекается из стека операндов текущей рамки (§2.6) и помещается в стек операндов рамки вызывающего метода. Любые другие значения в стеке операндов текущего метода удаляются.
Затем интерпретатор возвращает управление вызывающему методу, восстанавливая рамку вызывающего метода.
Исключения во время выполнения
Если реализация Java Virtual Machine не выполняет правила по структурированному блокированию, описанные в §2.11.10, то если текущий метод является методом synchronized, а текущий поток не является владельцем монитора, вошедшего или повторно вошедшего при вызове метода, lreturn выбрасывает исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит инструкцию monitorexit, но не инструкцию monitorenter для объекта, для которого вызывается метод synchronized.
В противном случае, если реализация Java Virtual Machine выполняет правила по структурированному блокированию, описанные в §2.11.10, и если первое из этих правил нарушается во время вызова текущего метода, то lreturn выбрасывает исключение IllegalMonitorStateException.
lshl
Операция
Сдвиг влево long
Формат
lshl
Формы
lshl = 121 (0x79)
Стек операндов
..., value1, value2 →
..., result
Описание
Значение value1 должно быть типа long, а value2 — типа int. Значения извлекаются из стека операндов. Вычисляется значение result путём сдвига value1 влево на s бит, где s — 6 младших битов value2. Значение result помещается в стек операндов.
Примечания
Это эквивалентно (даже при переполнении) умножению на 2 в степени s. Расстояние сдвига всегда находится в диапазоне от 0 до 63 включительно, как если бы value2 было подвергнуто побитовому логическому И с маской 0x3f.
lshr
Операция
Арифметический сдвиг вправо long
Формат
lshr
Формы
lshr = 123 (0x7b)
Стек операндов
..., value1, value2 →
..., result
Описание
Значение value1 должно быть типа long, а value2 — типа int. Значения извлекаются из стека операндов. Вычисляется значение result путём сдвига value1 вправо на s бит с расширением знака, где s — значение 6 младших битов value2. Значение result помещается в стек операндов.
Примечания
Полученное значение равно ⌊ value1 / 2s ⌋, где s равно value2 & 0x3f. Для неотрицательных value1 это эквивалентно усечению результата деления на 2 в степени s. Расстояние сдвига всегда находится в диапазоне от 0 до 63 включительно, как если бы value2 было подвергнуто побитовому логическому И с маской 0x3f.
lstore
Операция
Сохранить long в локальную переменную
Формат
lstore
индекс
Формы
lstore = 55 (0x37)
Стек операндов
..., значение →
...
Описание
Индекс — это беззнаковый байт. И индекс, и индекс+1 должны быть индексами в массиве локальных переменных текущей рамки (§2.6). Значение значение на вершине стека операндов должно быть типа long. Оно извлекается из стека операндов, а локальные переменные по индексом индекс и индекс+1 устанавливаются в значение значение.
Примечания
Инструкция lstore может быть использована совместно с инструкцией wide (§wide) для доступа к локальной переменной с использованием двубайтового беззнакового индекса.
lstore_
Операция
Сохранить long в локальную переменную
Формат
lstore_
Формы
lstore_0 = 63 (0x3f)
lstore_1 = 64 (0x40)
lstore_2 = 65 (0x41)
lstore_3 = 66 (0x42)
Стек операндов
..., значение →
...
Описание
И <n>, и <n>+1 должны быть индексами в массиве локальных переменных текущей рамки (§2.6). Значение значение на вершине стека операндов должно быть типа long. Оно извлекается из стека операндов, а локальные переменные по индексом <n> и <n>+1 устанавливаются в значение значение.
Примечания
Каждая из инструкций lstore_
lsub
Операция
Вычитание long
Формат
lsub
Формы
lsub = 101 (0x65)
Стек операндов
..., value1, value2 →
..., результат
Описание
Оба value1 и value2 должны быть типа long. Значения извлекаются из стека операндов. long результат равен value1 - value2. Результат помещается на стек операндов.
Для long вычитания, a-b производит тот же результат, что и a+(-b). Для long значений, вычитание из нуля равно отрицанию.
Результат представляет собой 64 младших бита истинного математического результата в достаточно широком формате со знаком, представленного как значение типа long. Если происходит переполнение, знак результата может отличаться от знака математической суммы двух значений.
Несмотря на то, что переполнение может произойти, выполнение инструкции lsub никогда не вызывает исключения во время выполнения.
lushr
Операция
Логический сдвиг вправо long
Формат
lushr
Формы
lushr = 125 (0x7d)
Стек операндов
..., value1, value2 →
..., результат
Описание
value1 должен быть типа long, а value2 — типа int. Значения извлекаются из стека операндов. long результат вычисляется путём логического сдвига value1 вправо (с расширением нулями) на величину, указанную 6 младшими битами value2. Результат помещается на стек операндов.
Примечания
Если value1 положительное, а s равно value2 & 0x3f, результат совпадает с результатом value1 >> s; если value1 отрицательное, результат равен значению выражения (value1 >> s) + (2L << ~s). Добавление члена (2L << ~s) компенсирует распространяемый знаковый бит. Расстояние сдвига, фактически используемое, всегда находится в диапазоне от 0 до 63 включительно.
lxor
Операция
Булево XOR long
Формат
lxor
Формы
lxor = 131 (0x83)
Стек операндов
..., value1, value2 →
..., результат
Описание
Оба value1 и value2 должны быть типа long. Они извлекаются из стека операндов. long результат вычисляется путём побитового исключающего ИЛИ value1 и value2. Результат помещается в стек операндов.
monitorenter
Операция
Вход в монитор для объекта
Формат
monitorenter
Формы
monitorenter = 194 (0xc2)
Стек операндов
..., objectref →
...
Описание
objectref должен быть типа reference.
Каждый объект связан с монитором. Монитор заблокирован, если и только если у него есть владелец. Поток, который выполняет monitorenter, пытается получить владение монитором, связанным с objectref, следующим образом:
-
Если счётчик входов монитора, связанного с objectref, равен нулю, поток входит в монитор и устанавливает счётчик входов в единицу. Затем этот поток становится владельцем монитора.
-
Если поток уже владеет монитором, связанным с objectref, он повторно входит в монитор, увеличивая счётчик входов.
-
Если другой поток уже владеет монитором, связанным с objectref, поток блокируется до тех пор, пока счётчик входов монитора не станет нулём, затем снова пытается получить владение.
Исключение во время выполнения
Если objectref является null, monitorenter генерирует исключение NullPointerException.
Примечания
Инструкция monitorenter может быть использована с одной или несколькими инструкциями monitorexit (§monitorexit) для реализации оператора блокировки в языке программирования Java (§3.14). Инструкции monitorenter и monitorexit не используются в реализации методов synchronized, хотя они могут быть использованы для предоставления эквивалентной семантики блокировки. Вход в монитор при вызове метода synchronized и выход из монитора при его возвращении неявно обрабатываются инструкцией вызова и возврата метода виртуальной машины Java, как если бы использовались инструкции monitorenter и monitorexit.
Связывание монитора с объектом может осуществляться различными способами, которые выходят за рамки этого спецификации. Например, монитор может быть выделен и освобожден одновременно с объектом. Или же он может быть динамически выделен в тот момент, когда поток пытается получить эксклюзивный доступ к объекту, и освобожден в какой-то момент позже, когда ни один поток больше не находится в мониторе для объекта.
Конструкции синхронизации языка программирования Java требуют поддержки операций над мониторами помимо входа и выхода. К ним относятся ожидание монитора (Object.wait) и уведомление других потоков, ожидающих монитора (Object.notifyAll и Object.notify). Эти операции поддерживаются в стандартном пакете java.lang, поставляемом с виртуальной машиной Java. Явный механизм поддержки этих операций не присутствует в наборе инструкций виртуальной машины Java.
monitorexit
Операция
Выход из монитора для объекта
Формат
monitorexit
Формы
monitorexit = 195 (0xc3)
Стек операндов
..., objectref →
...
Описание
objectref должен быть типа reference.
Поток, выполняющий monitorexit, должен быть владельцем монитора, связанного с экземпляром, на который ссылается objectref.
Поток уменьшает счетчик входов монитора, связанного с objectref. Если в результате значение счетчика равно нулю, поток выходит из монитора и больше не является его владельцем. Другие потоки, ожидающие входа в монитор, могут попытаться это сделать.
Исключения во время выполнения
Если objectref является null, monitorexit выбрасывает NullPointerException.
В противном случае, если поток, выполняющий monitorexit, не является владельцем монитора, связанного с экземпляром, на который ссылается objectref, monitorexit выбрасывает IllegalMonitorStateException.
В противном случае, если реализация Java Virtual Machine накладывает правила на структурированную блокировку, описанные в §2.11.10, и если второе из этих правил нарушается выполнением этой инструкции monitorexit, то monitorexit выбрасывает IllegalMonitorStateException.
Примечания
Одна или несколько инструкций monitorexit могут использоваться с инструкцией monitorenter (§monitorenter) для реализации оператора synchronized в языке программирования Java (§3.14). Инструкции monitorenter и monitorexit не используются при реализации методов synchronized, хотя они могут быть использованы для обеспечения эквивалентной семантики блокировки.
Java Virtual Machine поддерживает исключения, сгенерированные внутри методов synchronized и операторов synchronized по-разному:
-
Выход из монитора при нормальном завершении метода
synchronizedобрабатывается инструкциями возврата Java Virtual Machine. Выход из монитора при внезапном завершении методаsynchronizedнеявно обрабатывается инструкцией athrow Java Virtual Machine. -
Когда исключение генерируется внутри оператора
synchronized, выход из монитора, вошедшего до выполнения оператораsynchronized, достигается с помощью механизма обработки исключений Java Virtual Machine (§3.14).
многомерный массив
Операция
Создание нового многомерного массива
Формат
многомерный массив
индексбайт1
индексбайт2
размерности
Формы
многомерный массив = 197 (0xc5)
Стек операндов
..., счёт1, [счёт2, ...] →
..., ссылка_на_массив
Описание
Операнд размерности — это беззнаковый байт, который должен быть больше или равен 1. Он представляет количество измерений создаваемого массива. В стеке операндов должно быть размерности значений. Каждое из этих значений представляет количество компонентов в измерении создаваемого массива, должно быть типа int и должно быть неотрицательным. счёт1 — это желаемая длина в первом измерении, счёт2 — во втором и так далее.
Все значения счёт извлекаются из стека операндов. Беззнаковые индексбайт1 и индексбайт2 используются для построения индекса в пуле постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (индексбайт1 << 8) | индексбайт2. Элемент пула постоянных времени выполнения по этому индексу должен быть символической ссылкой на класс, массив или интерфейсный тип. Названный класс, массив или интерфейсный тип разрешаются (§5.4.3.1). Результирующий элемент должен быть типом массива с размерностью, большей или равной размерности.
Новый многомерный массив указанного типа выделяется из кучи сборки мусора. Если какое-либо значение счёт равно нулю, последующие измерения не выделяются. Компоненты массива в первом измерении инициализируются подмассивами типа второго измерения и так далее. Компоненты последнего выделенного измерения массива инициализируются стандартным начальным значением (§2.3, §2.4) для типа элемента типа массива. reference ссылка ссылка_на_массив на новый массив помещается в стек операндов.
Исключения связи
При разрешении символической ссылки на класс, массив или интерфейсный тип могут быть выброшены любые исключения, описанные в §5.4.3.1.
В противном случае, если у текущего класса нет разрешения на доступ к типу элемента разрешённого типа массива, многомерный массив вызывает IllegalAccessError.
Исключение времени выполнения
В противном случае, если любое из значений размерности в стеке операндов меньше нуля, инструкция многомерный массив вызывает NegativeArraySizeException.
Примечания
Для создания массива с одним измерением может быть эффективнее использовать newarray или anewarray (§newarray, §anewarray).
Класс массива, на который ссылается постоянный пул времени выполнения, может иметь больше измерений, чем операнд dimensions инструкции multianewarray. В этом случае создаются только первые dimensions измерений массива.
new
Операция
Создание нового объекта
Формат
new
indexbyte1
indexbyte2
Формы
new = 187 (0xbb)
Стек операндов
... →
..., objectref
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на тип класса или интерфейса. Названный тип класса или интерфейса разрешается (§5.4.3.1) и должен привести к типу класса. Память для нового экземпляра этого класса выделяется из кучи с автоматическим управлением памятью, а переменные экземпляра нового объекта инициализируются их значениями по умолчанию (§2.3, §2.4). objectref, ссылка на экземпляр, помещается в стек операндов.
При успешном разрешении класса он инициализируется (§5.5), если он еще не был инициализирован.
Исключения связывания
При разрешении символической ссылки на тип класса, массива или интерфейса могут быть выброшены любые исключения, описанные в §5.4.3.1.
В противном случае, если символическая ссылка на тип класса, массива или интерфейса разрешается на интерфейс или является типом abstract класса, new выбросит исключение InstantiationError.
Исключение времени выполнения
В противном случае, если выполнение этой инструкции new приводит к инициализации ссылаемого класса, new может выбросить исключение Error, как подробно описано в JLS §15.9.4.
Примечания
Инструкция new не полностью создает новый экземпляр; создание экземпляра не завершается до тех пор, пока метод инициализации экземпляра (§2.9) не будет вызван на неинициализированном экземпляре.
newarray
Операция
Создать новый массив
Формат
newarray
atype
Формы
newarray = 188 (0xbc)
Стек операндов
..., count →
..., arrayref
Описание
count должен быть типа int. Он извлекается из стека операндов. count представляет количество элементов создаваемого массива.
atype — код, указывающий тип создаваемого массива. Он должен принимать одно из следующих значений:
Таблица 6.1. Коды типов массивов
| Тип массива | atype |
|---|---|
T_BOOLEAN | 4 |
T_CHAR | 5 |
T_FLOAT | 6 |
T_DOUBLE | 7 |
T_BYTE | 8 |
T_SHORT | 9 |
T_INT | 10 |
T_LONG | 11 |
Создается новый массив, компоненты которого имеют тип atype и длину count, из кучи с автоматическим сбором мусора. В стек операндов помещается ссылка arrayref на этот новый объект массива. Каждый элемент нового массива инициализируется по умолчанию (§2.3, §2.4) для типа элемента типа массива.
Исключение во время выполнения
Если count меньше нуля, newarray генерирует исключение NegativeArraySizeException.
Примечания
В реализации виртуальной машины Java от Oracle массивы типа boolean (atype — T_BOOLEAN) хранятся как массивы 8-битных значений и обрабатываются инструкциями baload и bastore (§baload, §bastore), которые также обращаются к массивам типа byte. Другие реализации могут реализовать упакованные массивы boolean; инструкции baload и bastore по-прежнему должны использоваться для доступа к этим массивам.
nop
Операция
Ничего не делать
Формат
nop
Формы
nop = 0 (0x0)
Стек операндов
Без изменений
Описание
Ничего не делать.
pop
Операция
Извлечь верхнее значение из стека операндов
Формат
pop
Формы
pop = 87 (0x57)
Стек операндов
..., value →
...
Описание
Извлечь верхнее значение из стека операндов.
Инструкция pop не должна использоваться, если value не является значением вычислительного типа категории 1 (§2.11.1).
pop2
Операция
Извлечь верхнее одно или два значения из стека операндов
Формат
pop2
Формы
pop2 = 88 (0x58)
Стек операндов
Форма 1:
..., value2, value1 →
...
где каждое из value1 и value2 является значением вычислительного типа категории 1 (§2.11.1).
Форма 2:
..., value →
...
где value — значение вычислительного типа категории 2 (§2.11.1).
Описание
Извлечь верхнее одно или два значения из стека операндов.
putfield
Операция
Устанавливает поле в объекте
Формат
putfield
indexbyte1
indexbyte2
Формы
putfield = 181 (0xb5)
Стек операндов
..., objectref, value →
...
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения в этом индексе должен быть символической ссылкой на поле (§5.1), которое предоставляет имя и дескриптор поля, а также символическую ссылку на класс, в котором находится поле. Класс objectref не должен быть массивом. Если поле является protected (§4.6), и оно является членом суперкласса текущего класса, и поле не объявлено в той же пакетной среде выполнения (§5.3), что и текущий класс, то класс objectref должен быть либо текущим классом, либо подклассом текущего класса.
Ссылаемое поле разрешается (§5.4.3.2). Тип значения value, хранимого инструкцией putfield, должен быть совместим с дескриптором ссылаемого поля (§4.3.2). Если тип дескриптора поля является boolean, byte, char, short или int, то value должно быть int. Если тип дескриптора поля является float, long или double, то value должно быть соответственно float, long или double. Если тип дескриптора поля является типом ссылки, то value должно быть типа, совместимого с типом дескриптора поля по присваиванию (JLS §5.2). Если поле является final, оно должно быть объявлено в текущем классе, и инструкция должна выполняться в методе инициализации экземпляра (<init>) текущего класса (§2.9).
value и objectref извлекаются из стека операндов. objectref должен быть типа reference. value претерпевает преобразование в наборе значений (§2.8.3), что приводит к value', и ссылаемое поле в objectref устанавливается в value'.
Исключения при связывании
Во время разрешения символической ссылки на поле может быть возбуждено любое из исключений, относящихся к разрешению поля (§5.4.3.2).
В противном случае, если разрешенное поле является static полем, putfield возбуждает исключение IncompatibleClassChangeError.
В противном случае, если поле является final, оно должно быть объявлено в текущем классе, а инструкция должна выполняться в методе инициализации экземпляра (<init>) текущего класса. В противном случае возбуждается исключение IllegalAccessError.
Исключение во время выполнения
В противном случае, если objectref является null, инструкция putfield вызывает NullPointerException.
putstatic
Операция
Установить статическое поле в классе
Формат
putstatic
indexbyte1
indexbyte2
Формы
putstatic = 179 (0xb3)
Стек операндов
..., значение →
...
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на поле (§5.1), которая содержит имя и дескриптор поля, а также символическую ссылку на класс или интерфейс, в котором находится это поле. Ссылка на поле разрешается (§5.4.3.2).
При успешном разрешении поля, класс или интерфейс, в котором объявлено разрешенное поле, инициализируется (§5.5), если этот класс или интерфейс еще не был инициализирован.
Тип значения значение, хранимого инструкцией putstatic, должен быть совместим с дескриптором связанного поля (§4.3.2). Если тип дескриптора поля — boolean, byte, char, short или int, тогда значение должно быть int. Если тип дескриптора поля — float, long или double, тогда значение должно быть float, long или double соответственно. Если тип дескриптора поля — тип ссылки, тогда значение должно быть типа, совместимого с типом дескриптора поля (JLS §5.2). Если поле является final, оно должно быть объявлено в текущем классе, а инструкция должна выполняться в методе <clinit> текущего класса (§2.9).
Значение значение извлекается из стека операндов и подвергается преобразованию типа значения (§2.8.3), результатом чего является значение'. Поле класса устанавливается в значение'.
Исключения связывания
Во время разрешения символической ссылки на поле класса или интерфейса могут быть сгенерированы исключения, связанные с разрешением поля (§5.4.3.2).
В противном случае, если разрешенное поле не является полем класса (класса) или полем интерфейса, putstatic генерирует исключение IncompatibleClassChangeError.
В противном случае, если поле является final, оно должно быть объявлено в текущем классе, а инструкция должна выполняться в методе <clinit> текущего класса. В противном случае генерируется исключение IllegalAccessError.
Исключение во время выполнения
В противном случае, если выполнение этой инструкции putstatic вызывает инициализацию ссылаемого класса или интерфейса, putstatic может сгенерировать исключение Error, как подробно описано в §5.5.
Примечания
Инструкцию putstatic можно использовать только для задания значения поля интерфейса во время инициализации этого поля. Полям интерфейса можно присвоить значение только один раз, при выполнении выражения инициализации переменной интерфейса во время инициализации интерфейса (§5.5, JLS §9.3.1).
ret
Операция
Возврат из подпрограммы
Формат
ret
index
Формы
ret = 169 (0xa9)
Стек операндов
Без изменений
Описание
index — это беззнаковый байт от 0 до 255 включительно. Локальная переменная в текущей области (§2.6) с индексом index должна содержать значение типа returnAddress. Содержимое локальной переменной записывается в регистр pc виртуальной машины Java, и выполнение продолжается оттуда.
Примечания
Обратите внимание, что инструкция jsr (§jsr) помещает адрес на стек операндов, а ret извлекает его из локальной переменной. Эта асимметрия преднамеренная.
В реализации компилятора для языка программирования Java в Oracle до Java SE 6 инструкция ret использовалась с инструкциями jsr и jsr_w (§jsr, §jsr_w) при реализации условия finally (§3.13, §4.10.2.5).
Инструкцию ret не следует путать с инструкцией return (§return). Инструкция return возвращает управление от метода к своему вызывающему объекту без передачи значения обратно вызывающему объекту.
Операнд ret может использоваться в сочетании с инструкцией wide (§wide) для доступа к локальной переменной с помощью двубайтового беззнакового индекса.
return
Операция
Возврат void из метода
Формат
return
Формы
return = 177 (0xb1)
Стек операндов
... →
[пустой]
Описание
Текущий метод должен иметь тип возвращаемого значения void. Если текущий метод является методом synchronized, монитор, введённый или повторно введённый при вызове метода, обновляется и, возможно, выходит из состояния, как если бы была выполнена инструкция monitorexit (§monitorexit) в текущей нити. Если исключение не генерируется, все значения в стеке операндов текущей рамки (§2.6) удаляются.
Затем интерпретатор возвращает управление вызывающему методу, восстанавливая рамку вызывающего метода.
Исключения во время выполнения
Если реализация Java Virtual Machine не обеспечивает соблюдения правил структурированной блокировки, описанных в §2.11.10, то если текущий метод является методом synchronized, и текущая нить не является владельцем монитора, введённого или повторно введённого при вызове метода, return генерирует исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит инструкцию monitorexit, но не инструкцию monitorenter для объекта, над которым метод synchronized.
В противном случае, если реализация Java Virtual Machine обеспечивает соблюдение правил структурированной блокировки, описанных в §2.11.10, и если первое из этих правил нарушено во время вызова текущего метода, то return генерирует исключение IllegalMonitorStateException.
saload
Операция
Загрузка из массива short
Формат
saload
Формы
saload = 53 (0x35)
Стек операндов
..., arrayref, index →
..., value
Описание
arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип short. index должен быть типа int. Оба arrayref и index извлекаются из стека операндов. Компонент массива по индексу index извлекается и расширяется со знаком до int значения value. Это значение value помещается в стек операндов.
Исключения во время выполнения
Если arrayref является null, saload вызывает исключение NullPointerException.
В противном случае, если index не находится в пределах границ массива, на который ссылается arrayref, инструкция saload вызывает исключение ArrayIndexOutOfBoundsException.
sastore
Операция
Запись в массив short
Формат
sastore
Формы
sastore = 86 (0x56)
Стек операндов
..., arrayref, index, value →
...
Описание
arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип short. index и value должны быть типа int. arrayref, index и value извлекаются из стека операндов. Значение value усекается до short и сохраняется как компонент массива по индексу index.
Исключения во время выполнения
Если arrayref является null, sastore вызывает исключение NullPointerException.
В противном случае, если index не находится в пределах границ массива, на который ссылается arrayref, инструкция sastore вызывает исключение ArrayIndexOutOfBoundsException.
sipush
Операция
Поместить short
Формат
sipush
byte1
byte2
Формы
sipush = 17 (0x11)
Стек операндов
... →
..., value
Описание
Непосредственные беззнаковые значения byte1 и byte2 собираются в промежуточное значение short, где значение short равно (byte1 << 8) | byte2. Промежуточное значение затем расширяется со знаком до int value. Это значение value помещается в стек операндов.
swap
Операция
Поменять местами верхние два значения в стеке операндов
Формат
swap
Формы
swap = 95 (0x5f)
Стек операндов
..., value2, value1 →
..., value1, value2
Описание
Поменять местами верхние два значения в стеке операндов.
Инструкция swap не должна использоваться, если value1 и value2 являются значениями вычислительного типа категории 1 (§2.11.1).
Примечания
Виртуальная машина Java не предоставляет инструкцию, реализующую обмен операндами категории 2 вычислительных типов.
tableswitch
Операция
Доступ к таблице переходов по индексу и переход
Формат
tableswitch
<0-3 байт заполнения>
defaultbyte1
defaultbyte2
defaultbyte3
defaultbyte4
lowbyte1
lowbyte2
lowbyte3
lowbyte4
highbyte1
highbyte2
highbyte3
highbyte4
смещения переходов...
Формы
tableswitch = 170 (0xaa)
Стек операндов
..., индекс →
...
Описание
tableswitch — инструкция переменной длины. Сразу после кода операции tableswitch от 0 до 3 байтов должны использоваться в качестве заполнения, таким образом, чтобы defaultbyte1 начинался по адресу, кратно четырём байтам от начала текущего метода (кода операции его первой инструкции). Сразу после заполнения идут байты, представляющие собой три знаковых 32-битных значения: default, low и high. Сразу за ними следуют байты, представляющие собой серию high - low + 1 знаковых 32-битных смещений. Значение low должно быть меньше или равно high. high - low + 1 знаковых 32-битных смещений рассматриваются как таблица переходов с индексацией с 0. Каждое из этих знаковых 32-битных значений строится как (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4.
Значение индекс должно иметь тип int и извлекается из стека операндов. Если индекс меньше low или индекс больше high, то целевой адрес вычисляется путём добавления default к адресу кода операции этой инструкции tableswitch. В противном случае извлекается смещение в позиции индекс - low таблицы переходов. Целевой адрес вычисляется путём добавления этого смещения к адресу кода операции этой инструкции tableswitch. Выполнение затем продолжается по целевому адресу.
Целевой адрес, который может быть вычислен из каждого смещения таблицы переходов, а также из default, должен быть адресом кода операции инструкции внутри метода, содержащего эту инструкцию tableswitch.
Примечания
Требование выравнивания 4-байтовых операндов инструкции tableswitch гарантирует выравнивание этих операндов по 4 байтам тогда и только тогда, когда метод, содержащий инструкцию tableswitch, начинается на границе в 4 байта.
широкий
Операция
Увеличить индекс локальной переменной на дополнительные байты
Формат 1
широкий
<opcode>
indexbyte1
indexbyte2
где <opcode> — один из iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore или ret
Формат 2
широкий
iinc
indexbyte1
indexbyte2
constbyte1
constbyte2
Формы
широкий = 196 (0xc4)
Стек операндов
Такой же, как у изменённой инструкции
Описание
Инструкция wide изменяет поведение другой инструкции. Она принимает один из двух форматов, в зависимости от изменяемой инструкции. Первый формат инструкции wide изменяет одну из инструкций iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore или ret (§iload, §fload, §aload, §lload, §dload, §istore, §fstore, §astore, §lstore, §dstore, §ret). Второй формат применяется только к инструкции iinc (§iinc).
В обоих случаях, сам оператор wide в скомпилированном коде следует за оператором инструкции, которую wide изменяет. В обоих форматах два беззнаковых байта indexbyte1 и indexbyte2 следуют за изменённым оператором и собираются в 16-битный беззнаковый индекс локальной переменной в текущей области видимости (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Вычисленный индекс должен соответствовать индексу массива локальных переменных текущей области видимости. Где инструкция wide изменяет инструкцию lload, dload, lstore или dstore, индекс, следующий за вычисленным индексом (индекс + 1), также должен соответствовать индексу массива локальных переменных. Во втором формате два непосредственных беззнаковых байта constbyte1 и constbyte2 следуют за indexbyte1 и indexbyte2 в потоке кода. Эти байты также собираются в знаковый 16-битный констант, где константа равна (constbyte1 << 8) | constbyte2.
Расширенный байткод работает нормально, за исключением использования расширенного индекса и, в случае второго формата, большего диапазона приращения.
Примечания
Хотя мы говорим, что wide "изменяет поведение другой инструкции", инструкция wide фактически рассматривает байты, составляющие изменённую инструкцию, как операнды, тем самым денатурируя встроенную инструкцию. В случае модифицированной инструкции iinc, один из логических операндов iinc даже не находится в обычном смещении от оператора. Встроенную инструкцию никогда нельзя выполнять напрямую; её оператор никогда не должен быть целью какой-либо инструкции передачи управления.
© Oracle and/or its affiliates. All rights reserved.
Licensed under the Oracle Technology Network License Agreement.