Глава 6. Набор команд виртуальной машины Java
Оглавление
-
- aaload
- aastore
- aconst_null
- aload
- aload_
- anewarray
- areturn
- arraylength
- astore
- astore_
- athrow
- baload
- bastore
- bipush
- caload
- castore
- checkcast
- d2f
- d2i
- d2l
- dadd
- daload
- dastore
- dcmp<op>
- dconst_
- ddiv
- dload
- dload_
- dmul
- dneg
- drem
- dreturn
- dstore
- dstore_
- dsub
- dup
- dup_x1
- dup_x2
- dup2
- dup2_x1
- dup2_x2
- f2d
- f2i
- f2l
- fadd
- faload
- fastore
- fcmp<op>
- fconst_
- fdiv
- fload
- fload_
- fmul
- fneg
- frem
- freturn
- fstore
- fstore_
- fsub
- getfield
- getstatic
- goto
- goto_w
- i2b
- i2c
- i2d
- i2f
- i2l
- i2s
- iadd
- iaload
- iand
- iastore
- iconst_
- idiv
- if_acmp<cond>
- if_icmp<cond>
- if<cond>
- ifnonnull
- ifnull
- iinc
- iload
- iload_
- imul
- ineg
- instanceof
- invokedynamic
- invokeinterface
- invokespecial
- invokestatic
- invokevirtual
- ior
- irem
- ireturn
- ishl
- ishr
- istore
- istore_<n>
- isub
- iushr
- ixor
- jsr
- jsr_w
- l2d
- l2f
- l2i
- ladd
- laload
- land
- lastore
- lcmp
- lconst_<l>
- ldc
- ldc_w
- ldc2_w
- ldiv
- lload
- lload_<n>
- lmul
- lneg
- lookupswitch
- lor
- lrem
- lreturn
- lshl
- lshr
- lstore
- lstore_<n>
- lsub
- lushr
- lxor
- monitorenter
- monitorexit
- multianewarray
- new
- newarray
- nop
- pop
- pop2
- putfield
- putstatic
- ret
- return
- saload
- sastore
- sipush
- swap
- tableswitch
- wide
Инструкция виртуальной машины Java состоит из кода операции, определяющего выполняемое действие, за которым следуют нулевые или более операндов, содержащих значения, над которыми выполняется операция. В этой главе подробно описывается формат каждой инструкции виртуальной машины Java и операция, которую она выполняет.
Описание каждой инструкции всегда даётся в контексте кода виртуальной машины Java, который удовлетворяет статическим и структурным ограничениям §4 (Формат файла class). В описании отдельных инструкций виртуальной машины Java часто указывается, что какая-то ситуация "должна" или "не должна" быть: "Значение value2 должно быть типа int". Ограничения §4 (Формат файла class) гарантируют, что все такие ожидания будут в действительности выполнены. Если какое-либо ограничение («должен» или «не должен») в описании инструкции не выполняется во время выполнения, поведение виртуальной машины Java не определено.
Виртуальная машина Java проверяет, что код виртуальной машины Java удовлетворяет статическим и структурным ограничениям на этапе компоновки с помощью class-верификатора файлов (§4.10). Таким образом, виртуальная машина Java будет пытаться выполнить код только из действительных файлов class. Выполнение проверки на этапе компоновки привлекательно тем, что проверки выполняются только один раз, существенно уменьшая объём работы, который должен быть выполнен во время выполнения. Другие стратегии реализации возможны, при условии, что они соответствуют Спецификации языка Java, издание Java SE 11 и Спецификации виртуальной машины Java, издание Java SE 11.
В дополнение к кодам операций инструкций, указанных позже в этой главе, которые используются в файлах class (§4 (Формат файла class)), три кода операций зарезервированы для внутреннего использования реализацией виртуальной машины Java. Если в будущем набор инструкций виртуальной машины Java будет расширен, эти зарезервированные коды операций гарантированно не будут использоваться.
Два из зарезервированных кодов операций, числа 254 (0xfe) и 255 (0xff), имеют мнемоники impdep1 и impdep2 соответственно. Эти инструкции предназначены для предоставления «задних дверей» или ловушек для функциональности, специфичной для реализации, реализованной в программном и аппаратном обеспечении соответственно. Третий зарезервированный код операции, номер 202 (0xca), имеет мнемонику breakpoint и предназначен для использования отладчиками для реализации точек останова.
Хотя эти коды операций зарезервированы, они могут использоваться только внутри реализации виртуальной машины Java. Они не могут появляться в действительных файлах class. Такие инструменты, как отладчики или генераторы JIT-кода (§2.13), которые могут напрямую взаимодействовать с кодом виртуальной машины Java, который уже загружен и выполнен, могут встретить эти коды операций. Такие инструменты должны пытаться вести себя корректно, если они столкнутся с любой из этих зарезервированных инструкций.
Реализация Java Virtual Machine выбрасывает объект, являющийся экземпляром подкласса класса VirtualMachineError, когда внутренняя ошибка или ограничение ресурсов препятствуют выполнению семантики, описанной в этой главе. Данное спецификация не может предсказать, где могут возникнуть внутренние ошибки или ограничения ресурсов, и не предписывает, когда именно они могут быть сообщены. Таким образом, любой из подклассов VirtualMachineError, определённых ниже, может быть выброшен в любое время во время работы Java Virtual Machine:
-
InternalError: В реализации Java Virtual Machine произошла внутренняя ошибка из-за сбоя в программном обеспечении, реализующем виртуальную машину, сбоя в программном обеспечении базовой операционной системы или сбоя в аппаратном обеспечении. Эта ошибка доставляется асинхронно (§2.10) при обнаружении и может возникнуть в любой точке программы. -
OutOfMemoryError: Реализация Java Virtual Machine исчерпала виртуальную или физическую память, и автоматический менеджер хранения не смог освободить достаточно памяти для удовлетворения запроса на создание объекта. -
StackOverflowError: Реализация Java Virtual Machine исчерпала стек памяти для потока, обычно из-за неограниченного числа рекурсивных вызовов потока в результате сбоя в выполняемой программе. -
UnknownError: Произошло исключение или ошибка, но реализация Java Virtual Machine не может сообщить об actual исключении или ошибке.
Инструкции Java Virtual Machine в этой главе представлены в виде записей следующего формата, в алфавитном порядке, и каждая запись начинается с новой страницы.
мнемоника
Операция
Краткое описание инструкции
Формат
мнемоника
операнд1
операнд2
...
Формы
мнемоника = код операции
Стек операндов
..., значение1, значение2 →
..., значение3
Описание
Более подробное описание, описывающее ограничения содержимого стека операндов или записей константного пула, выполняемой операции, тип результата и т. д.
Исключения привязки
Если какие-либо исключения привязки могут быть выброшены в результате выполнения этой инструкции, они устанавливаются по одной строке, в порядке, в котором они должны быть выброшены.
Исключения выполнения
Если какие-либо исключения выполнения могут быть выброшены в результате выполнения инструкции, они устанавливаются по одной строке, в порядке, в котором они должны быть выброшены.
Помимо исключений привязки и исключений выполнения, если таковые имеются, для данной инструкции, эта инструкция не должна вызывать никаких исключений выполнения, кроме экземпляров VirtualMachineError или его подклассов.
Примечания
Комментарии, не являющиеся строго частью спецификации инструкции, помещаются как примечания в конце описания.
Каждая ячейка в диаграмме формата инструкции представляет собой один 8-битный байт. Мнемоника инструкции — её имя. Код операции — её числовое представление, приведённое в десятичной и шестнадцатеричной формах. Только числовое представление фактически присутствует в коде Java Virtual Machine в файле class.
Следует помнить, что существуют "операнды", генерируемые на этапе компиляции и встроенные в инструкции Java Virtual Machine, а также "операнды", вычисляемые во время выполнения и предоставляемые в стеке операндов. Несмотря на то, что они поступают из нескольких источников, все эти операнды представляют одно и то же: значения, над которыми будет выполняться операция инструкции Java Virtual Machine. Явно используя многие из своих операндов из стека операндов, вместо того чтобы явно представлять их в своём скомпилированном коде в виде дополнительных байтов операндов, номеров регистров и т. д., код Java Virtual Machine остаётся компактным.
Некоторые инструкции представлены как члены семейства родственных инструкций, имеющих общее описание, формат и диаграмму стека операндов. Таким образом, семейство инструкций включает несколько кодов операций и мнемоник кодов операций; в диаграмме формата инструкции появляется только мнемоника семейства, а отдельный ряд форм перечисляет все мнемоники и коды операций членов семейства. Например, строка форм для семейства инструкций lconst_<l>, предоставляющая информацию о мнемонике и кодах операций для двух инструкций в этом семействе (lconst_0 и lconst_1), выглядит так:
lconst_0 = 9 (0x9)
lconst_1 = 10 (0xa)
В описании инструкций Java Virtual Machine воздействие выполнения инструкции на стек операндов (§2.6.2) текущей рамки (§2.6) представлено текстово, причём стек растёт слева направо, и каждое значение представлено отдельно. Таким образом,
..., значение1, значение2 →
..., результат
показывает операцию, начинающуюся с значение2 на вершине стека операндов, а значение1 — непосредственно под ним. В результате выполнения инструкции значение1 и значение2 извлекаются из стека операндов и заменяются вычисленным значением результат. Остальная часть стека операндов, представленная многоточием (...), не изменяется в результате выполнения инструкции.
Значения типов long и double представлены одной записью в стеке операндов.
В первом издании Спецификации виртуальной машины Java значения в стеке операндов типов long и double каждый представлялись в диаграмме стека двумя записями.
aaload
Операция
Загрузка reference из массива
Формат
aaload
Формы
aaload = 50 (0x32)
Стек операндов
..., arrayref, index →
..., value
Описание
arrayref должен быть типа reference и должен ссылаться на массив, компоненты которого имеют тип reference. index должен быть типа int. Оба arrayref и index извлекаются из стека операндов. Значение value в компоненте массива по индексу index извлекается и помещается в стек операндов.
Исключения во время выполнения
Если arrayref является null, то aaload генерирует исключение NullPointerException.
В противном случае, если index выходит за пределы массива, на который ссылается arrayref, то инструкция aaload генерирует исключение ArrayIndexOutOfBoundsException.
aastore
Операция
Запись в массив reference
Формат
aastore
Формы
aastore = 83 (0x53)
Стек операндов
..., arrayref, index, value →
...
Описание
arrayref должен быть типа reference и должен ссылаться на массив, компоненты которого имеют тип reference. index должен быть типа int, а value — типа reference. arrayref, index и value извлекаются из стека операндов.
Если value является null, то value сохраняется как компонент массива по индексу index.
В противном случае, value не является null. Если тип value совместим с типом компонентов массива, на который ссылается arrayref, то value сохраняется как компонент массива по индексу index.
Следующие правила используются для определения совместимости value с типом компонентов массива, если value не является null. Если S — тип объекта, на который ссылается value, а T — тип компонентов массива, то aastore определяет совместимость присваивания следующим образом:
-
Если S — тип класса, то:
-
Если T — тип класса, то S должен быть тем же классом, что и T, или S должен быть подклассом T;
-
Если T — тип интерфейса, то S должен реализовывать интерфейс T.
-
-
Если S — тип массива SC
[], то есть массив компонентов типа SC, то:-
Если T — тип класса, то T должен быть
Object. -
Если T — тип интерфейса, то T должен быть одним из интерфейсов, реализованных массивами (JLS §4.10.3).
-
Если T — тип массива TC
[], то есть массив компонентов типа TC, то одно из следующих условий должно выполняться:-
TC и SC — один и тот же примитивный тип.
-
TC и SC — типы ссылок, и тип SC присваивается TC по этим правилам выполнения.
-
-
Исключения во время выполнения
Если arrayref является null, то aastore генерирует исключение NullPointerException.
В противном случае, если index выходит за пределы массива, на который ссылается arrayref, то инструкция aastore генерирует исключение ArrayIndexOutOfBoundsException.
В противном случае, если arrayref не является null и фактический тип не-null value не совместим с фактическим типом компонентов массива, то aastore генерирует исключение ArrayStoreException.
aconst_null
Операция
Поместить null
Формат
aconst_null
Формы
aconst_null = 1 (0x1)
Стек операндов
... →
..., null
Описание
Поместить null объект reference в стек операндов.
Примечания
Виртуальная машина Java не навязывает конкретное значение для null.
aload
Операция
Загрузка reference из локальной переменной
Формат
aload
index
Формы
aload = 25 (0x19)
Стек операндов
... →
..., objectref
Описание
Значение index представляет собой беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу index должна содержать reference. Ссылка на объект objectref в локальной переменной по индексу index помещается в стек операндов.
Примечания
Инструкция aload не может использоваться для загрузки значения типа returnAddress из локальной переменной в стек операндов. Эта асимметрия с инструкцией astore (§astore) является намеренной.
Код операции aload может использоваться совместно с инструкцией wide (§wide) для доступа к локальной переменной с использованием двубайтного беззнакового индекса.
aload_<n>
Операция
Загрузка reference из локальной переменной
Формат
aload_<n>
Формы
aload_0 = 42 (0x2a)
aload_1 = 43 (0x2b)
aload_2 = 44 (0x2c)
aload_3 = 45 (0x2d)
Стек операндов
... →
..., objectref
Описание
Значение <n> должно быть индексом в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу <n> должна содержать reference. Ссылка на объект objectref в локальной переменной по индексу <n> помещается в стек операндов.
Примечания
Инструкция aload_<n> не может использоваться для загрузки значения типа returnAddress из локальной переменной в стек операндов. Эта асимметрия с соответствующей инструкцией astore_<n> (§astore_<n>) является намеренной.
Каждая из инструкций aload_<n> идентична инструкции aload с индексом <n>, за исключением того, что операнд <n> является неявным.
anewarray
Операция
Создание нового массива reference
Формат
anewarray
indexbyte1
indexbyte2
Формы
anewarray = 189 (0xbd)
Стек операндов
..., count →
..., arrayref
Описание
Значение count должно быть типа int. Оно извлекается из стека операндов. Значение count представляет количество элементов создаваемого массива. Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения по этому индексу должен быть символьной ссылкой на класс, массив или интерфейс. Имя класса, массива или интерфейса разрешается (§5.4.3.1). Создается новый массив с элементами указанного типа и длиной count, выделяется из кучи сборки мусора, и ссылка на этот новый объект массива arrayref помещается в стек операндов. Все элементы нового массива инициализируются null, значением по умолчанию для типов reference (§2.4).
Исключения при связывании
При разрешении символьной ссылки на класс, массив или интерфейс могут быть выброшены исключения, описанные в §5.4.3.1.
Исключения во время выполнения
В противном случае, если count меньше нуля, инструкция anewarray выбросит исключение NegativeArraySizeException.
Примечания
Инструкция anewarray используется для создания одномерного массива ссылок на объекты или части многомерного массива.
areturn
Операция
Возвращение reference из метода
Формат
areturn
Формы
areturn = 176 (0xb0)
Стек операндов
..., objectref →
[пусто]
Описание
objectref должен быть типа reference и должен ссылаться на объект типа, совместимого с типом возврата (JLS §5.2) представленного в описателе метода (§4.3.3) текущего метода. Если текущий метод является методом synchronized, монитор, в который вошли или в который повторно вошли при вызове метода, обновляется и, возможно, выходит, как будто выполняется инструкция monitorexit (§monitorexit) в текущем потоке. Если исключение не возникает, objectref извлекается из стека операндов текущей рамки (§2.6) и помещается в стек операндов рамки вызывающего метода. Любые другие значения в стеке операндов текущего метода удаляются.
Затем интерпретатор восстанавливает рамку вызывающего метода и возвращает управление вызывающему методу.
Исключения во время выполнения
Если реализация Java Virtual Machine не соблюдает правила структурированной блокировки, описанные в §2.11.10, то если текущий метод является методом synchronized, а текущий поток не является владельцем монитора, в который вошли или в который повторно вошли при вызове метода, areturn генерирует исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит инструкцию monitorexit, но не инструкцию monitorenter, для объекта, на котором метод синхронизирован.
В противном случае, если реализация Java Virtual Machine соблюдает правила структурированной блокировки, описанные в §2.11.10, и если первое из этих правил нарушается во время вызова текущего метода, то areturn генерирует исключение IllegalMonitorStateException.
arraylength
Операция
Получить длину массива
Формат
arraylength
Формы
arraylength = 190 (0xbe)
Стек операндов
..., arrayref →
..., length
Описание
arrayref должен быть типа reference и должен ссылаться на массив. Он извлекается из стека операндов. Определяется длина length массива, на который он ссылается. Эта длина length помещается в стек операндов в качестве int.
Исключения во время выполнения
Если arrayref является null, инструкция arraylength генерирует исключение NullPointerException.
astore
Операция
Сохранить reference в локальную переменную
Формат
astore
index
Формы
astore = 58 (0x3a)
Стек операндов
..., objectref →
...
Описание
index — это беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей рамки (§2.6). objectref вверху стека операндов должен быть типа returnAddress или типа reference. Он извлекается из стека операндов, и значение локальной переменной по индексу index устанавливается в objectref.
Примечания
Инструкция astore используется с objectref типа returnAddress при реализации фрагмента finally языка программирования Java (§3.13).
Инструкция aload (§aload) не может использоваться для загрузки значения типа returnAddress из локальной переменной в стек операндов. Эта асимметрия с инструкцией astore намеренна.
Код операции astore может использоваться вместе с инструкцией wide (§wide), чтобы получить доступ к локальной переменной, используя двухбайтовый беззнаковый индекс.
astore_
Операция
Сохранить 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 при реализации finally пунктов языка программирования Java (§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 Virtual Machine Oracle массивы boolean (массивы типа T_BOOLEAN (§2.2, §newarray)) реализуются как массивы 8-битовых значений. Другие реализации могут реализовывать упакованные массивы boolean; инструкция baload таких реализаций должна использоваться для доступа к этим массивам.
bastore
Операция
Запись в массив byte или boolean
Формат
bastore
Формы
bastore = 84 (0x54)
Стек операндов
..., arrayref, index, value →
...
Описание
arrayref должен быть типа reference и должен ссылаться на массив, компоненты которого имеют тип byte или boolean. index и value должны быть типа int. arrayref, index и value извлекаются из стека операндов.
Если arrayref ссылается на массив, компоненты которого имеют тип byte, то значение value усекается до byte и сохраняется в качестве компонента массива по индексу index.
Если arrayref ссылается на массив, компоненты которого имеют тип boolean, то значение value сужается, взяв побитовое И от value и 1; результат сохраняется в качестве компонента массива по индексу index.
Исключения во время выполнения
Если arrayref является null, bastore генерирует исключение NullPointerException.
В противном случае, если index не находится в пределах границ массива, на который ссылается arrayref, инструкция bastore генерирует исключение ArrayIndexOutOfBoundsException.
Примечания
Инструкция bastore используется для записи значений в массивы byte и boolean. В реализации Java Virtual Machine Oracle массивы 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 — тип массива SC
[], т.е. массив компонентов типа SC, то:-
Если T — тип класса, то T должен быть
Object. -
Если T — тип интерфейса, то T должен быть одним из интерфейсов, реализуемых массивами (JLS §4.10.3).
-
Если T — тип массива TC
[], т.е. массив компонентов типа TC, то одно из следующих условий должно быть истинным:-
TC и SC — один и тот же примитивный тип.
-
TC и SC — типы ссылок, и тип SC может быть приведён к TC путём рекурсивного применения этих правил.
-
-
Исключения при связывании
При разрешении символической ссылки на класс, массив или тип интерфейса может быть выброшено любое из исключений, описанных в §5.4.3.1.
Исключение во время выполнения
В противном случае, если objectref не может быть приведён к разрешённому типу класса, массива или интерфейса, инструкция checkcast генерирует исключение ClassCastException.
Примечания
Инструкция checkcast очень похожа на инструкцию instanceof (§instanceof). Они различаются обработкой null, поведением при неудачном тесте (checkcast генерирует исключение, instanceof помещает код результата) и воздействием на стек операндов.
d2f
Операция
Преобразование double в float
Формат
d2f
Формы
d2f = 144 (0x90)
Стек операндов
..., value →
..., result
Описание
value на вершине стека операндов должен быть типа double. Он извлекается из стека операндов и преобразуется с помощью преобразования набора значений (§2.8.3), получая value'. Затем value' преобразуется в результат типа float с использованием режима округления IEEE 754 до ближайшего значения. Результат result помещается в стек операндов.
Если инструкция d2f является FP-строгой (§2.8.2), результат преобразования всегда округляется до ближайшего представимого значения в наборе значений типа float (§2.3.2).
Если инструкция d2f не является FP-строгой, результат преобразования может быть взят из набора значений float с расширенным порядком (§2.3.2); он не обязательно округляется до ближайшего представимого значения в наборе значений типа float.
Конечное значение value' слишком маленькое для представления как float, преобразуется в ноль того же знака; конечное значение value' слишком большое для представления как float, преобразуется в бесконечность того же знака. double NaN преобразуется в float NaN.
Примечания
Инструкция d2f выполняет сужающее приведение примитивных типов (JLS §5.1.3). Она может потерять информацию о величине value' и может также потерять точность.
d2i
Операция
Преобразовать double в int
Формат
d2i
Формы
d2i = 142 (0x8e)
Стек операндов
..., значение →
..., результат
Описание
Значение значение в вершине стека операндов должно быть типа double. Оно извлекается из стека операндов и подвергается преобразованию типа (§2.8.3), в результате чего получается значение'. Затем значение' преобразуется в int. Результат помещается в стек операндов:
-
Если значение' равно NaN, результат преобразования равен
int0. -
В противном случае, если значение' не является бесконечностью, оно округляется до целого значения V, используя режим округления IEEE 754 к нулю. Если это целое значение V может быть представлено как
int, то результат — это значениеintV. -
В противном случае, либо значение' слишком мало (отрицательное значение большой величины или отрицательная бесконечность), и результат — это наименьшее представимое значение типа
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)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа double. Значения извлекаются из стека операндов и подвергаются преобразованию типа (§2.8.3), в результате чего получаются значение1' и значение2'. Результат результат равен значение1' + значение2'. Результат помещается в стек операндов.
Результат инструкции dadd определяется правилами арифметики IEEE:
-
Если значение1' или значение2' равно NaN, результат — NaN.
-
Сумма двух бесконечностей с разными знаками — NaN.
-
Сумма двух бесконечностей с одинаковыми знаками — бесконечность с этим знаком.
-
Сумма бесконечности и любого конечного значения равна этой бесконечности.
-
Сумма двух нулей с разными знаками — положительный ноль.
-
Сумма двух нулей с одинаковыми знаками — ноль с этим знаком.
-
Сумма нуля и ненулевого конечного значения равна этому ненулевому значению.
-
Сумма двух ненулевых конечных значений с одинаковой величиной и разными знаками — положительный ноль.
-
В остальных случаях, где ни один операнд не является бесконечностью, нулём или NaN и значения имеют одинаковый знак или разную величину, сумма вычисляется и округляется до ближайшего представимого значения с использованием режима округления IEEE 754 до ближайшего. Если величина слишком велика для представления как
double, мы говорим, что операция переполнилась; результат — бесконечность соответствующего знака. Если величина слишком мала для представления какdouble, мы говорим, что операция переполнилась; результат — ноль соответствующего знака.
Java Virtual Machine требует поддержки постепенного переполнения, как определено в IEEE 754. Несмотря на то, что может произойти переполнение, переполнение или потеря точности, выполнение инструкции dadd никогда не генерирует исключение во время выполнения.
daload
Операция
Загрузка double из массива
Формат
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
Операция
Сохранение в массив double
Формат
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', то значение 1 помещается в стек операндов.
-
Если value1' равно value2', то значение 0 помещается в стек операндов.
-
Если value1' меньше value2', то значение -1 помещается в стек операндов.
-
Если хотя бы одно из value1' или value2' является NaN, то инструкция dcmpg помещает значение 1, а dcmpl — значение -1 в стек операндов.
Сравнение с плавающей точкой выполняется в соответствии со стандартом IEEE 754. Все значения, кроме NaN, упорядочены. Отрицательная бесконечность меньше всех конечных значений, а положительная бесконечность больше всех конечных значений. Положительный и отрицательный нули считаются равными.
Примечания
Инструкции dcmpg и dcmpl отличаются только обработкой сравнений, включающих NaN. NaN неупорядочен, поэтому любое сравнение с участием NaN терпит неудачу, если один или оба операнда являются NaN. Наличие как dcmpg, так и dcmpl позволяет компилировать любое сравнение так, чтобы оно помещало одно и то же result в стек операндов, независимо от того, потерпел ли неудачу сравнение на не-NaN значениях или встретил NaN. Более подробную информацию см. в §3.5.
dconst_<d>
Операция
Поместить double
Формат
dconst_<d>
Формы
dconst_0 = 14 (0xe)
dconst_1 = 15 (0xf)
Стек операндов
... →
..., <d>
Описание
Поместить константу double <d> (0.0 или 1.0) в стек операндов.
ddiv
Операция
Деление
Формат
ddiv
Формы
ddiv = 111 (0x6f)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба value1 и value2 должны быть типа double. Значения извлекаются из стека операндов и претерпевают преобразование типов (§2.8.3), в результате чего получаются value1' и value2'. Полученное значение result равно value1' / value2'. Результат помещается в стек операндов.
Результат инструкции ddiv регулируется правилами IEEE арифметики:
-
Если value1' или value2' равно NaN, результат NaN.
-
Если ни value1' ни value2' не NaN, знак результата положительный, если оба значения имеют одинаковый знак, и отрицательный, если знаки разные.
-
Деление бесконечности на бесконечность приводит к NaN.
-
Деление бесконечности на конечное значение приводит к бесконечности соответствующего знака, как указано выше.
-
Деление конечного значения на бесконечность приводит к знаку нуля, как указано выше.
-
Деление нуля на ноль приводит к NaN; деление нуля на любое другое конечное значение приводит к знаку нуля, как указано выше.
-
Деление ненулевого конечного значения на ноль приводит к бесконечности соответствующего знака, как указано выше.
-
В остальных случаях, когда ни один операнд не является бесконечностью, нулём или NaN, частное вычисляется и округляется до ближайшего
doubleв режиме округления IEEE 754 до ближайшего. Если величина слишком велика для представления какdouble, то говорят о переполнении; результат тогда — бесконечность соответствующего знака. Если величина слишком мала для представления какdouble, то говорят об обнулении; результат тогда — ноль соответствующего знака.
Виртуальная машина Java требует поддержки постепенного обнуления, как определено в IEEE 754. Несмотря на то, что могут возникнуть переполнение, обнуление, деление на ноль или потеря точности, выполнение инструкции ddiv никогда не вызывает исключения во время выполнения.
dload
Операция
Загрузка double из локальной переменной
Формат
dload
index
Формы
dload = 24 (0x18)
Стек операндов
... →
..., value
Описание
index — беззнаковый байт. index и index+1 должны быть индексами в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу index должна содержать double. Значение локальной переменной по индексу index помещается в стек операндов.
Примечания
Инструкция dload может использоваться в сочетании с инструкцией wide (§wide) для доступа к локальной переменной с помощью двубайтового беззнакового индекса.
dload_<n>
Операция
Загрузка double из локальной переменной
Формат
dload_<n>
Формы
dload_0 = 38 (0x26)
dload_1 = 39 (0x27)
dload_2 = 40 (0x28)
dload_3 = 41 (0x29)
Стек операндов
... →
..., value
Описание
И <n> и <n>+1 должны быть индексами в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу <n> должна содержать double. Значение локальной переменной по индексу <n> помещается в стек операндов.
Примечания
Каждая из инструкций dload_<n> эквивалентна dload с index = <n>, за исключением того, что операнд <n> неявный.
dmul
Операция
Умножить double
Формат
dmul
Формы
dmul = 107 (0x6b)
Стек операндов
..., value1, value2 →
..., результат
Описание
Оба value1 и value2 должны быть типа double. Значения извлекаются из стека операндов и преобразуются в соответствии с правилами преобразования наборов значений (§2.8.3), что приводит к value1' и value2'. double результатом является value1' * value2'. Значение результат помещается в стек операндов.
Результат инструкции 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)
Стек операндов
..., value →
..., результат
Описание
Значение должно быть типа double. Оно извлекается из стека операндов и преобразуется в соответствии с правилами преобразования наборов значений (§2.8.3), что приводит к value'. double результат является арифметическим отрицанием value'. результат помещается в стек операндов.
Для double значений, отрицание не равно вычитанию из нуля. Если x является +0.0, то 0.0-x равно +0.0, но -x равно -0.0. Унарный минус просто меняет знак double.
Особые случаи:
-
Если операнд — NaN, результатом является NaN (помните, что NaN не имеет знака).
-
Если операнд — бесконечность, результатом является бесконечность с противоположным знаком.
-
Если операнд — ноль, результатом является ноль с противоположным знаком.
drem
Операция
Остаток double
Формат
drem
Формы
drem = 115 (0x73)
Стек операндов
..., value1, value2 →
..., результат
Описание
Оба value1 и value2 должны быть типа double. Значения извлекаются из стека операндов и подвергаются преобразованию набора значений (§2.8.3), что приводит к value1' и value2'. Результат вычисляется и помещается в стек операндов как 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, остаток с плавающей точкой результат от делимого value1' и делителя value2' определяется математическим соотношением результат = 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
index
Формы
dstore = 57 (0x39)
Стек операндов
..., value →
...
Описание
index — это байт без знака. И index, и index+1 должны быть индексами в массив локальных переменных текущей фрейма (§2.6). Значение value на вершине стека операндов должно быть типа double. Оно извлекается из стека операндов и преобразуется с помощью преобразования набора значений (§2.8.3), в результате чего получается value'. Локальные переменные по индексам index и index+1 устанавливаются в value'.
Примечания
Команда dstore может использоваться совместно с инструкцией wide (§wide), чтобы получить доступ к локальной переменной с помощью двубайтного индекса без знака.
dstore_<n>
Операция
Сохранить double в локальную переменную
Формат
dstore_<n>
Формы
dstore_0 = 71 (0x47)
dstore_1 = 72 (0x48)
dstore_2 = 73 (0x49)
dstore_3 = 74 (0x4a)
Стек операндов
..., value →
...
Описание
И <n>, и <n>+1 должны быть индексами в массив локальных переменных текущей фрейма (§2.6). Значение value на вершине стека операндов должно быть типа double. Оно извлекается из стека операндов и преобразуется с помощью преобразования набора значений (§2.8.3), в результате чего получается value'. Локальные переменные по индексам <n> и <n>+1 устанавливаются в value'.
Примечания
Каждая из инструкций dstore_<n> аналогична dstore с индексом <n>, за исключением того, что операнд <n> неявный.
dsub
Операция
Вычесть double
Формат
dsub
Формы
dsub = 103 (0x67)
Стек операндов
..., value1, value2 →
..., result
Описание
И value1, и value2 должны быть типа double. Значения извлекаются из стека операндов и преобразуются с помощью преобразования набора значений (§2.8.3), в результате чего получаются value1' и value2'. Результат result — это value1' - value2'. Результат помещается в стек операндов.
При вычитании, всегда верно, что double даёт тот же результат, что и a+(-b). Однако для инструкции dsub вычитание из нуля не равно отрицанию, потому что если x равно +0.0, то 0.0-x равно +0.0, но -x равно -0.0.
Виртуальная машина Java требует поддержки постепенного обнуления, как определено в IEEE 754. Несмотря на то, что может произойти переполнение, подхват или потеря точности, выполнение инструкции dsub никогда не вызывает исключения во время выполнения.
dup
Операция
Дублировать значение вершины стека операндов
Формат
dup
Формы
dup = 89 (0x59)
Стек операндов
..., value →
..., value, value
Описание
Дублировать верхнее значение в стеке операндов и поместить дублированное значение в стек операндов.
Инструкция dup не должна использоваться, если value является значением типа вычислительной категории 1 (§2.11.1).
dup_x1
Операция
Дублирует верхнее значение стека операндов и вставляет его на две позиции ниже.
Формат
dup_x1
Формы
dup_x1 = 90 (0x5a)
Стек операндов
..., value2, value1 →
..., value1, value2, value1
Описание
Дублирует верхнее значение в стеке операндов и вставляет дубликат на две позиции ниже в стеке операндов.
Инструкцию dup_x1 следует использовать только в том случае, если как value1, так и value2 являются значениями вычислительного типа категории 1 (§2.11.1).
dup_x2
Операция
Дублирует верхнее значение стека операндов и вставляет его на две или три позиции ниже.
Формат
dup_x2
Формы
dup_x2 = 91 (0x5b)
Стек операндов
Форма 1:
..., value3, value2, value1 →
..., value1, value3, value2, value1
где value1, value2 и value3 — значения вычислительного типа категории 1 (§2.11.1).
Форма 2:
..., value2, value1 →
..., value1, value2, value1
где value1 — значение вычислительного типа категории 1, а value2 — значение вычислительного типа категории 2 (§2.11.1).
Описание
Дублирует верхнее значение стека операндов и вставляет дубликат на две или три позиции ниже в стеке операндов.
dup2
Операция
Дублирует одно или два верхних значения стека операндов.
Формат
dup2
Формы
dup2 = 92 (0x5c)
Стек операндов
Форма 1:
..., value2, value1 →
..., value2, value1, value2, value1
где value1 и value2 — значения вычислительного типа категории 1 (§2.11.1).
Форма 2:
..., value →
..., value, value
где value — значение вычислительного типа категории 2 (§2.11.1).
Описание
Дублирует одно или два верхних значения стека операндов и возвращает дублированные значения в исходном порядке в стек операндов.
dup2_x1
Операция
Дублирует одно или два верхних значения стека операндов и вставляет их на две или три позиции ниже.
Формат
dup2_x1
Формы
dup2_x1 = 93 (0x5d)
Стек операндов
Форма 1:
..., value3, value2, value1 →
..., value2, value1, value3, value2, value1
где value1, value2 и value3 — значения вычислительного типа категории 1 (§2.11.1).
Форма 2:
..., value2, value1 →
..., value1, value2, value1
где value1 — значение вычислительного типа категории 2, а value2 — значение вычислительного типа категории 1 (§2.11.1).
Описание
Дублирует одно или два верхних значения стека операндов и вставляет дублированные значения в исходном порядке на одну позицию ниже исходного значения или значений в стеке операндов.
dup2_x2
Операция
Дублирует верхнее или два верхних значения стека операндов и вставляет их на два, три или четыре позиции ниже.
Формат
dup2_x2
Формы
dup2_x2 = 94 (0x5e)
Стек операндов
Форма 1:
..., value4, value3, value2, value1 →
..., value2, value1, value4, value3, value2, value1
где value1, value2, value3 и value4 — значения вычислительного типа категории 1 (§2.11.1).
Форма 2:
..., value3, value2, value1 →
..., value1, value3, value2, value1
где value1 — значение вычислительного типа категории 2, а value2 и value3 — значения вычислительного типа категории 1 (§2.11.1).
Форма 3:
..., value3, value2, value1 →
..., value2, value1, value3, value2, value1
где value1 и value2 — значения вычислительного типа категории 1, а value3 — значение вычислительного типа категории 2 (§2.11.1).
Форма 4:
..., value2, value1 →
..., value1, value2, value1
где value1 и value2 — значения вычислительного типа категории 2 (§2.11.1).
Описание
Дублирует верхнее или два верхних значения в стеке операндов и вставляет дублированные значения в исходном порядке в стек операндов.
f2d
Операция
Преобразовать float в double
Формат
f2d
Формы
f2d = 141 (0x8d)
Стек операндов
..., value →
..., result
Описание
Значение value на вершине стека операндов должно быть типа float. Оно извлекается из стека операндов и преобразуется посредством преобразования множества значений (§2.8.3), что приводит к value'. Затем value' преобразуется в double result. Это result помещается в стек операндов.
Примечания
Если инструкция f2d строго выполняет операции с плавающей точкой (§2.8.2), она выполняет расширяющее преобразование примитивного типа (JLS §5.1.2). Поскольку все значения множества значений float (§2.3.2) точно представимы значениями множества значений double (§2.3.2), такое преобразование точно.
Если инструкция f2d не строго выполняет операции с плавающей точкой, результат преобразования может быть взят из множества значений с расширенной экспонентой double; он не обязательно округляется до ближайшего представимого значения в множестве значений double. Однако, если операнд value взят из множества значений с расширенной экспонентой float, и целевой результат ограничен множеством значений double, может потребоваться округлить value.
f2i
Операция
Преобразовать float в int
Формат
f2i
Формы
f2i = 139 (0x8b)
Стек операндов
..., value →
..., result
Описание
Значение value на вершине стека операндов должно быть типа float. Оно извлекается из стека операндов и преобразуется посредством преобразования множества значений (§2.8.3), что приводит к value'. Затем value' преобразуется в int result. Это result помещается в стек операндов:
-
Если value' равно NaN, результат преобразования — целое число 0.
-
В противном случае, если value' не является бесконечностью, оно округляется до целого значения V с округлением к нулю в соответствии с режимом IEEE 754 округления к нулю. Если это целое значение V может быть представлено как
int, то result — значение V типаint. -
В противном случае, либо value' слишком мало (отрицательное значение большой величины или отрицательная бесконечность), и result — наименьшее представимое значение типа
int, либо value' слишком велико (положительное значение большой величины или положительная бесконечность), и result — наибольшее представимое значение типаint.
Примечания
Инструкция f2i выполняет сужающее преобразование примитивного типа (JLS §5.1.3). Она может потерять информацию о величине value' и может также потерять точность.
f2l
Операция
Преобразовать float в long
Формат
f2l
Формы
f2l = 140 (0x8c)
Стек операндов
..., значение →
..., результат
Описание
Значение значение на вершине стека операндов должно быть типа float. Оно извлекается из стека операндов и подвергается преобразованию типа (§2.8.3), что приводит к значение'. Затем значение' преобразуется в long результат. Этот результат помещается в стек операндов:
-
Если значение' равно NaN, результатом преобразования является
long0. -
В противном случае, если значение' не является бесконечностью, оно округляется до целого значения V, округляя к нулю в соответствии с режимом округления IEEE 754. Если это целое значение V может быть представлено как
long, то результат равенlongзначению V. -
В противном случае, либо значение' слишком мало (отрицательное значение большой величины или отрицательная бесконечность), и результат является наименьшим представимым значением типа
long, либо значение' слишком велико (положительное значение большой величины или положительная бесконечность), и результат является наибольшим представимым значением типаlong.
Примечания
Инструкция f2l выполняет сужающее преобразование примитивных типов (JLS §5.1.3). Она может потерять информацию о масштабе значение' и может также потерять точность.
fadd
Операция
Сложить float
Формат
fadd
Формы
fadd = 98 (0x62)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
И значение1, и значение2 должны быть типа float. Значения извлекаются из стека операндов и подвергаются преобразованию типов (§2.8.3), что приводит к значение1' и значение2'. float результат — это значение1' + значение2'. Результат помещается в стек операндов.
Результат инструкции fadd определяется правилами арифметики IEEE:
-
Если значение1' или значение2' равно NaN, результат равен NaN.
-
Сумма двух бесконечностей с разными знаками равна NaN.
-
Сумма двух бесконечностей с одинаковыми знаками равна бесконечности с тем же знаком.
-
Сумма бесконечности и любого конечного значения равна бесконечности.
-
Сумма двух нулей с разными знаками равна положительному нулю.
-
Сумма двух нулей с одинаковыми знаками равна нулю с тем же знаком.
-
Сумма нуля и ненулевого конечного значения равна ненулевому значению.
-
Сумма двух ненулевых конечных значений одинаковой величины и противоположных знаков равна положительному нулю.
-
В остальных случаях, когда ни один из операндов не является бесконечностью, нулём или NaN, и значения имеют одинаковый знак или разную величину, сумма вычисляется и округляется до ближайшего представимого значения с использованием режима округления IEEE 754. Если величина слишком велика для представления как
float, мы говорим, что операция переполняется; результат тогда равен бесконечности с соответствующим знаком. Если величина слишком мала для представления какfloat, мы говорим, что операция подполняется; результат тогда равен нулю с соответствующим знаком.
Виртуальная машина Java требует поддержки постепенного подполнения, как определено в IEEE 754. Несмотря на то, что могут произойти переполнение, подпополнение или потеря точности, выполнение инструкции fadd никогда не генерирует исключение во время выполнения.
faload
Операция
Загрузить float из массива
Формат
faload
Формы
faload = 48 (0x30)
Стек операндов
..., ссылка_на_массив, индекс →
..., значение
Описание
ссылка_на_массив должна быть типа reference и должна ссылаться на массив, элементы которого имеют тип float. Индекс должен быть типа int. И ссылка_на_массив, и индекс извлекаются из стека операндов. Значение float в элементе массива по индексу извлекается и помещается в стек операндов.
Исключения во время выполнения
Если ссылка_на_массив является null, faload генерирует исключение NullPointerException.
В противном случае, если индекс выходит за пределы массива, на который ссылается ссылка_на_массив, инструкция faload генерирует исключение ArrayIndexOutOfBoundsException.
fastore
Операция
Сохранить в массив float
Формат
fastore
Формы
fastore = 81 (0x51)
Стек операндов
..., arrayref, index, value →
...
Описание
arrayref должен быть типа reference и должен ссылаться на массив, компоненты которого имеют тип float. index должен быть типа int, а value — типа float. arrayref, index и value извлекаются из стека операндов. Значение value преобразуется согласно преобразованию набора значений (§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_<f>
Операция
Поместить float
Формат
fconst_<f>
Формы
fconst_0 = 11 (0xb)
fconst_1 = 12 (0xc)
fconst_2 = 13 (0xd)
Стек операндов
... →
..., <f>
Описание
Поместить константу float <f> (0.0, 1.0 или 2.0) в стек операндов.
fdiv
Операция
Деление float
Формат
fdiv
Формы
fdiv = 110 (0x6e)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа float. Значения извлекаются из стека операндов и подвергаются преобразованию (§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 Virtual Machine требует поддержки постепенного подполения, как определено в IEEE 754. Несмотря на то, что может произойти переполнение, подполение, деление на ноль или потеря точности, выполнение инструкции fdiv никогда не вызывает исключения во время выполнения.
fload
Операция
Загрузка float из локальной переменной
Формат
fload
индекс
Формы
fload = 23 (0x17)
Стек операндов
... →
..., значение
Описание
Индекс — это беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу должна содержать float. Значение локальной переменной по индексу помещается в стек операндов.
Замечания
Инструкция fload может использоваться в сочетании с инструкцией wide (§wide) для доступа к локальной переменной с помощью двухбайтного беззнакового индекса.
fload_<n>
Операция
Загрузка float из локальной переменной
Формат
fload_<n>
Формы
fload_0 = 34 (0x22)
fload_1 = 35 (0x23)
fload_2 = 36 (0x24)
fload_3 = 37 (0x25)
Стек операндов
... →
..., значение
Описание
<n> — индекс в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по <n> должна содержать float. Значение локальной переменной по <n> помещается в стек операндов.
Замечания
Каждая из инструкций fload_<n> эквивалентна fload с индексом <n>, за исключением того, что операнд <n> неявный.
fmul
Операция
Умножение float
Формат
fmul
Формы
fmul = 106 (0x6a)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба value1 и value2 должны быть типа float. Значения извлекаются из стека операндов и подвергаются преобразованию типов (§2.8.3), в результате чего получаются value1' и value2'. float result равно value1' * value2'. result помещается в стек операндов.
Результат инструкции 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'. float 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 определяет frem как аналогичную виртуальным машинам Java целочисленным инструкциям остатка (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 не соблюдает правила структурированного блокирования, описанные в §2.11.10, то если текущий метод является методом synchronized, а текущий поток не является владельцем монитора, введённого или повторно введённого при вызове метода, freturn вызывает исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит инструкцию monitorexit, но не инструкцию monitorenter, для объекта, на котором синхронизируется метод.
В противном случае, если реализация виртуальной машины Java соблюдает правила структурированного блокирования, описанные в §2.11.10, и если первое из этих правил нарушается во время вызова текущего метода, freturn вызывает исключение IllegalMonitorStateException.
fstore
Операция
Сохранить float в локальной переменной
Формат
fstore
индекс
Формы
fstore = 56 (0x38)
Стек операндов
..., значение →
...
Описание
Индекс — это беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей рамки (§2.6). Значение в верхней части стека операндов должно быть типа float. Оно извлекается из стека операндов и подвергается преобразованию набора значений (§2.8.3), что приводит к значение'. Значение локальной переменной по индексу индекс устанавливается в значение'.
Примечания
Команда fstore может использоваться совместно с инструкцией wide (§wide), чтобы получить доступ к локальной переменной с помощью двубайтного беззнакового индекса.
fstore_<n>
Операция
Сохранить float в локальной переменной
Формат
fstore_<n>
Формы
fstore_0 = 67 (0x43)
fstore_1 = 68 (0x44)
fstore_2 = 69 (0x45)
fstore_3 = 70 (0x46)
Стек операндов
..., значение →
...
Описание
<n> должен быть индексом в массиве локальных переменных текущей рамки (§2.6). Значение в верхней части стека операндов должно быть типа float. Оно извлекается из стека операндов и подвергается преобразованию набора значений (§2.8.3), что приводит к значение'. Значение локальной переменной по индексу <n> устанавливается в значение'.
Примечания
Каждая из инструкций fstore_<n> аналогична fstore с индексом <n>, за исключением того, что операнд <n> неявный.
fsub
Операция
Вычесть float
Формат
fsub
Формы
fsub = 102 (0x66)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа float. Значения извлекаются из стека операндов и подвергаются преобразованию набора значений (§2.8.3), что приводит к значение1' и значение2'. Результат результат равен значение1' - значение2'. Результат помещается в стек операндов.
Для float вычитания всегда верно, что a-b дает тот же результат, что и a+(-b). Однако для инструкции fsub вычитание из нуля не то же самое, что отрицание, потому что если x равно +0.0, то 0.0-x равно +0.0, но -x равно -0.0.
Виртуальная машина Java требует поддержки постепенного недотека, как определено в IEEE 754. Несмотря на то, что может произойти переполнение, недотека или потеря точности, выполнение инструкции fsub никогда не вызывает исключения во время выполнения.
getfield
Операция
Извлечение поля из объекта
Формат
getfield
indexbyte1
indexbyte2
Формы
getfield = 180 (0xb4)
Стек операндов
..., objectref →
..., значение
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на поле (§5.1), которая содержит имя и дескриптор поля, а также символическую ссылку на класс, в котором находится поле. Ссылка на поле разрешается (§5.4.3.2).
objectref, тип которого должен быть reference, но не тип массива, извлекается из стека операндов. Значение value ссылающегося поля в objectref извлекается и помещается в стек операндов.
Исключения при связывании
При разрешении символической ссылки на поле могут быть выброшены любые ошибки, связанные с разрешением поля (§5.4.3.2).
В противном случае, если разрешенное поле является static полем, getfield выбрасывает IncompatibleClassChangeError.
Исключение во время выполнения
В противном случае, если objectref является null, инструкция getfield выбрасывает исключение NullPointerException.
Примечания
Инструкция getfield не может использоваться для доступа к полю length массива. Вместо этого используется инструкция arraylength (§arraylength).
getstatic
Операция
Получение static поля из класса
Формат
getstatic
indexbyte1
indexbyte2
Формы
getstatic = 178 (0xb2)
Стек операндов
..., →
..., значение
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на поле (§5.1), которая содержит имя и дескриптор поля, а также символическую ссылку на класс или интерфейс, в котором находится поле. Ссылка на поле разрешается (§5.4.3.2).
При успешном разрешении поля, класс или интерфейс, объявивший разрешенное поле, инициализируется, если этот класс или интерфейс еще не был инициализирован (§5.5).
Значение value поля класса или интерфейса извлекается и помещается в стек операндов.
Исключения при связывании
При разрешении символической ссылки на поле класса или интерфейса могут быть выброшены любые исключения, связанные с разрешением поля (§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
Operation
Безусловный переход (широкий индекс)
Format
goto_w
branchbyte1
branchbyte2
branchbyte3
branchbyte4
Forms
goto_w = 200 (0xc8)
Operand Stack
Без изменений
Description
Беззнаковые байты branchbyte1, branchbyte2, branchbyte3 и branchbyte4 используются для построения знакового 32-битного branchoffset, где branchoffset равно (branchbyte1 << 24) | (branchbyte2 << 16) | (branchbyte3 << 8) | branchbyte4. Выполнение продолжается по этому смещению от адреса кода операции этой инструкции goto_w. Целевой адрес должен быть адресом кода операции инструкции в методе, который содержит эту инструкцию goto_w.
Notes
Хотя инструкция goto_w принимает 4-байтовое смещение ветвления, другие факторы ограничивают размер метода до 65535 байт (§4.11). Это ограничение может быть повышено в будущей версии Java Virtual Machine.
i2b
Operation
Преобразовать int в byte
Format
i2b
Forms
i2b = 145 (0x91)
Operand Stack
..., value →
..., result
Description
Значение value в вершине стека операндов должно быть типа int. Оно извлекается из стека операндов, усекается до byte, затем расширяется по знаку до int result. Этот result помещается в стек операндов.
Notes
Инструкция i2b выполняет сужающее примитивное преобразование (JLS §5.1.3). Она может потерять информацию о общей величине value. result также может не иметь того же знака, что и value.
i2c
Operation
Преобразовать int в char
Format
i2c
Forms
i2c = 146 (0x92)
Operand Stack
..., value →
..., result
Description
Значение value в вершине стека операндов должно быть типа int. Оно извлекается из стека операндов, усекается до char, затем расширяется нулями до int result. Этот result помещается в стек операндов.
Notes
Инструкция i2c выполняет сужающее примитивное преобразование (JLS §5.1.3). Она может потерять информацию о общей величине value. result (который всегда положителен) также может не иметь того же знака, что и value.
i2d
Operation
Преобразовать int в double
Format
i2d
Forms
i2d = 135 (0x87)
Operand Stack
..., value →
..., result
Description
Значение value в вершине стека операндов должно быть типа int. Оно извлекается из стека операндов и преобразуется в double result. result помещается в стек операндов.
Notes
Инструкция 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)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
значение1 и значение2 должны быть типа int. Значения извлекаются из стека операндов. Результат — это значение1 + значение2. Результат помещается в стек операндов.
Результат — 32 младших бита истинного математического результата в достаточно широком формате со знаком дополнительной величины, представленного как значение типа int. Если происходит переполнение, то знак результата может не совпадать со знаком математической суммы двух значений.
Несмотря на то, что переполнение может произойти, выполнение инструкции iadd никогда не генерирует исключение во время выполнения.
iaload
Операция
Загрузить int из массива
Формат
iaload
Формы
iaload = 46 (0x2e)
Стек операндов
..., ссылкаНаМассив, индекс →
..., значение
Описание
ссылкаНаМассив должна быть типа reference и должна ссылаться на массив, компоненты которого имеют тип int. Индекс должен быть типа int. СсылкаНаМассив и индекс извлекаются из стека операндов. Значение компонента массива по индексу извлекается и помещается в стек операндов.
Исключения во время выполнения
Если ссылкаНаМассив является null, iaload генерирует исключение NullPointerException.
В противном случае, если индекс не входит в пределы массива, на который ссылается ссылкаНаМассив, инструкция iaload генерирует исключение ArrayIndexOutOfBoundsException.
iand
Операция
Логическое И int
Формат
iand
Формы
iand = 126 (0x7e)
Стек операндов
..., value1, value2 →
..., результат
Описание
Оба value1 и value2 должны быть типа int. Они извлекаются из стека операндов. Вычисляется int результат путём побитового И (конъюнкции) value1 и value2. Результат помещается в стек операндов.
iastore
Операция
Сохранение в int массив
Формат
iastore
Формы
iastore = 79 (0x4f)
Стек операндов
..., arrayref, index, value →
...
Описание
arrayref должен быть типа reference и ссылаться на массив, элементы которого типа int. Оба index и value должны быть типа int. arrayref, index и value извлекаются из стека операндов. Значение value сохраняется в элементе массива с индексом index.
Исключения во время выполнения
Если arrayref является null, iastore генерирует исключение NullPointerException.
В противном случае, если index не находится в пределах массива, на который ссылается arrayref, инструкция iastore генерирует исключение ArrayIndexOutOfBoundsException.
iconst_<i>
Операция
Положить int константу
Формат
iconst_<i>
Формы
iconst_m1 = 2 (0x2)
iconst_0 = 3 (0x3)
iconst_1 = 4 (0x4)
iconst_2 = 5 (0x5)
iconst_3 = 6 (0x6)
iconst_4 = 7 (0x7)
iconst_5 = 8 (0x8)
Стек операндов
... →
..., <i>
Описание
Поместить int константу <i> (-1, 0, 1, 2, 3, 4 или 5) в стек операндов.
Примечания
Каждая из инструкций этой группы эквивалентна bipush <i> для соответствующего значения <i>, за исключением того, что операнд <i> неявный.
idiv
Операция
Деление int
Формат
idiv
Формы
idiv = 108 (0x6c)
Стек операндов
..., value1, value2 →
..., результат
Описание
Оба value1 и value2 должны быть типа int. Значения извлекаются из стека операндов. int результат — значение выражения языка программирования Java value1 / value2. Результат помещается в стек операндов.
Деление int округляет к нулю; то есть, частное, вычисленное для int значений в n/d, — это int значение q, модуль которого как можно больше, при условии |d ⋅ q| ≤ |n|. Кроме того, q положительно, когда |n| ≥ |d| и n и d одного знака, но q отрицательно, когда |n| ≥ |d| и n и d разного знака.
Есть один особый случай, который не удовлетворяет этому правилу: если делимое — наибольшее по модулю отрицательное целое число для типа int, а делитель — -1, то происходит переполнение, и результат равен делимому. Несмотря на переполнение, исключение в этом случае не генерируется.
Исключение во время выполнения
Если значение делителя при int делении равно 0, idiv генерирует исключение ArithmeticException.
if_acmp<cond>
Операция
Ветвление, если reference сравнение успешно
Формат
if_acmp<cond>
branchbyte1
branchbyte2
Формы
if_acmpeq = 165 (0xa5)
if_acmpne = 166 (0xa6)
Стек операндов
..., value1, value2 →
...
Описание
Оба value1 и value2 должны быть типа reference. Оба извлекаются из стека операндов и сравниваются. Результаты сравнения следующие:
-
if_acmpeq успешно, если и только если value1 = value2
-
if_acmpne успешно, если и только если value1 ≠ value2
Если сравнение успешно, беззнаковые branchbyte1 и branchbyte2 используются для построения знакового 16-битного смещения, где смещение вычисляется как (branchbyte1 << 8) | branchbyte2. Выполнение затем продолжается по этому смещению от адреса инструкции 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. Выполнение затем продолжается по этому смещению от адреса инструкции opcode данного if_icmp<cond>. Целевой адрес должен быть адресом opcode инструкции в методе, содержащем эту инструкцию if_icmp<cond>.
В противном случае, выполнение продолжается по адресу инструкции, следующей за этой инструкцией if_icmp<cond>.
if<cond>
Операция
Ветвление, если int сравнение с нулём успешно
Формат
if<cond>
branchbyte1
branchbyte2
Формы
ifeq = 153 (0x99)
ifne = 154 (0x9a)
iflt = 155 (0x9b)
ifge = 156 (0x9c)
ifgt = 157 (0x9d)
ifle = 158 (0x9e)
Стек операндов
..., value →
...
Описание
Значение value должно быть типа int. Оно извлекается из стека операндов и сравнивается с нулём. Все сравнения являются знаковыми. Результаты сравнений таковы:
-
ifeq успешно, если и только если value = 0
-
ifne успешно, если и только если value ≠ 0
-
iflt успешно, если и только если value < 0
-
ifle успешно, если и только если value ≤ 0
-
ifgt успешно, если и только если value > 0
-
ifge успешно, если и только если value ≥ 0
Если сравнение успешно, незначащие branchbyte1 и branchbyte2 используются для построения знакового 16-разрядного смещения, где смещение вычисляется как (branchbyte1 << 8) | branchbyte2. Выполнение затем продолжается по этому смещению от адреса кода этой инструкции if<cond>. Целевой адрес должен быть адресом кода инструкции внутри метода, содержащего эту инструкцию if<cond>.
В противном случае выполнение продолжается по адресу инструкции, следующей за этой инструкцией if<cond>.
ifnonnull
Операция
Ветвление, если reference не null
Формат
ifnonnull
branchbyte1
branchbyte2
Формы
ifnonnull = 199 (0xc7)
Стек операндов
..., value →
...
Описание
value должно быть типа reference. Оно извлекается из стека операндов. Если value не null, незначащие branchbyte1 и branchbyte2 используются для построения знакового 16-разрядного смещения, где смещение вычисляется как (branchbyte1 << 8) | branchbyte2. Выполнение затем продолжается по этому смещению от адреса кода этой инструкции ifnonnull. Целевой адрес должен быть адресом кода инструкции внутри метода, содержащего эту инструкцию ifnonnull.
В противном случае выполнение продолжается по адресу инструкции, следующей за этой инструкцией ifnonnull.
ifnull
Операция
Ветвление, если reference равно null
Формат
ifnull
branchbyte1
branchbyte2
Формы
ifnull = 198 (0xc6)
Стек операндов
..., value →
...
Описание
value должно быть типа reference. Оно извлекается из стека операндов. Если value равно null, незначащие branchbyte1 и branchbyte2 используются для построения знакового 16-разрядного смещения, где смещение вычисляется как (branchbyte1 << 8) | branchbyte2. Выполнение затем продолжается по этому смещению от адреса кода этой инструкции ifnull. Целевой адрес должен быть адресом кода инструкции внутри метода, содержащего эту инструкцию ifnull.
В противном случае выполнение продолжается по адресу инструкции, следующей за этой инструкцией ifnull.
iinc
Операция
Увеличение локальной переменной на константу
Формат
iinc
index
const
Формы
iinc = 132 (0x84)
Стек операндов
Без изменений
Описание
index – беззнаковый байт, должен быть индексом в массиве локальных переменных текущего фрейма (§2.6). const – непосредственный знаковый байт. Локальная переменная в позиции index должна содержать int. Значение const сначала расширяется со знаком до int, а затем локальная переменная в позиции index увеличивается на эту величину.
Примечания
Инструкция iinc может использоваться совместно с инструкцией wide (§wide), чтобы получить доступ к локальной переменной с помощью двухбайтового беззнакового индекса и увеличить её на двухбайтовое знаковое значение.
iload
Операция
Загрузка int из локальной переменной
Формат
iload
индекс
Формы
iload = 21 (0x15)
Стек операндов
... →
..., значение
Описание
Индекс — это беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу должна содержать int. Значение локальной переменной по индексу помещается в стек операндов.
Примечания
Код операции iload может быть использован совместно с инструкцией wide (§wide) для доступа к локальной переменной с помощью двухбайтного беззнакового индекса.
iload_<n>
Операция
Загрузка int из локальной переменной
Формат
iload_<n>
Формы
iload_0 = 26 (0x1a)
iload_1 = 27 (0x1b)
iload_2 = 28 (0x1c)
iload_3 = 29 (0x1d)
Стек операндов
... →
..., значение
Описание
<n> должно быть индексом в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по <n> должна содержать int. Значение локальной переменной по <n> помещается в стек операндов.
Примечания
Каждая из инструкций iload_<n> аналогична iload с индексом <n>, за исключением того, что операнд <n> неявный.
imul
Операция
Умножение int
Формат
imul
Формы
imul = 104 (0x68)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
значение1 и значение2 должны быть типа int. Значения извлекаются из стека операндов. Результат результат равен значение1 * значение2. Результат помещается в стек операндов.
Результат — это 32 младших бита истинного математического результата в достаточно широком формате дополнения до двух, представленного как значение типа int. Если происходит переполнение, то знак результата может не совпадать со знаком математического умножения двух значений.
Несмотря на то, что может произойти переполнение, выполнение инструкции imul никогда не вызывает исключение времени выполнения.
ineg
Операция
Отрицание int
Формат
ineg
Формы
ineg = 116 (0x74)
Стек операндов
..., значение →
..., результат
Описание
Значение должно быть типа int. Оно извлекается из стека операндов. Результат результат — это арифметическое отрицание значения, -значение. Результат помещается в стек операндов.
Для значений int, отрицание аналогично вычитанию из нуля. Поскольку Java Virtual Machine использует представление целых чисел в дополнении до двух, и диапазон значений в дополнении до двух не симметричен, отрицание максимального отрицательного int приводит к тому же максимальному отрицательному числу. Несмотря на то, что произошло переполнение, исключение не генерируется.
Для всех значений int x, -x равно (~x)+1.
instanceof
Операция
Определяет, является ли объект заданного типа
Формат
instanceof
indexbyte1
indexbyte2
Формы
instanceof = 193 (0xc1)
Стек операндов
..., objectref →
..., результат
Описание
objectref, который должен быть типа reference, извлекается из стека операндов. Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Запись в пуле постоянных времени выполнения по этому индексу должна быть символической ссылкой на класс, массив или тип интерфейса.
Если objectref является null, инструкция instanceof помещает значение результат 0 в качестве int на стек операндов.
В противном случае, указанный класс, массив или тип интерфейса разрешаются (§5.4.3.1). Если objectref является экземпляром разрешённого класса или типа массива, или реализует разрешённый интерфейс, инструкция instanceof помещает значение результат 1 в качестве int на стек операндов; в противном случае, помещает значение результат 0.
Следующие правила используются для определения того, является ли objectref, который не является null, экземпляром разрешённого типа. Если S — тип объекта, на который ссылается objectref, а T — разрешённый класс, массив или тип интерфейса, тогда instanceof определяет, является ли objectref экземпляром T следующим образом:
-
Если S — тип класса, то:
-
Если T — тип класса, то S должен быть тем же классом, что и T, или S должен быть подклассом T;
-
Если T — тип интерфейса, то S должен реализовывать интерфейс T.
-
-
Если S — тип массива SC
[], то есть массив компонентов типа SC, то:-
Если T — тип класса, то T должен быть
Object. -
Если T — тип интерфейса, то T должен быть одним из интерфейсов, реализуемых массивами (JLS §4.10.3).
-
Если T — тип массива TC
[], то есть массив компонентов типа TC, то одно из следующих утверждений должно быть истинным:-
TC и SC — один и тот же примитивный тип.
-
TC и SC — ссылочные типы, и тип SC может быть приведён к типу TC по этим правилам времени выполнения.
-
-
Исключения при связывании
При разрешении символической ссылки на класс, массив или тип интерфейса могут быть выброшены любые исключения, описанные в §5.4.3.1.
Примечания
Инструкция instanceof очень похожа на инструкцию checkcast (§checkcast). Она отличается обработкой null, поведением при неудачной проверке ( checkcast выбрасывает исключение, instanceof помещает код результата) и влиянием на стек операндов.
invokedynamic
Операция
Вызов динамически вычисленной точки вызова
Формат
invokedynamic
indexbyte1
indexbyte2
0
0
Формы
invokedynamic = 186 (0xba)
Стек операндов
..., [arg1, [arg2 ...]] →
...
Описание
Сначала беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пул постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения по этому индексу должен быть символической ссылкой на динамически вычисленную точку вызова (§5.1). Значения третьего и четвёртого байтов операнда должны всегда быть нулевыми.
Символическая ссылка разрешается (§5.4.3.6) для этой конкретной инструкции invokedynamic для получения reference к экземпляру java.lang.invoke.CallSite. Экземпляр java.lang.invoke.CallSite считается "связанным" с этой конкретной инструкцией invokedynamic.
Экземпляр java.lang.invoke.CallSite указывает на обработчик метода. Значения аргументов nargs извлекаются из стека операндов, и вызывается обработчик метода. Вызов происходит так, как если бы выполнялась инструкция invokevirtual, которая указывает на индекс в пуле постоянных времени выполнения на символическую ссылку R, где:
-
R является символической ссылкой на метод класса;
-
для символической ссылки на класс, в котором должен находиться метод, R указывает на
java.lang.invoke.MethodHandle; -
для имени метода, R указывает на
invokeExact; -
для описателя метода, R указывает на описатель метода в динамически вычисленной точке вызова.
и как если бы следующие элементы были добавлены в стек операндов в указанном порядке:
-
ссылка на обработчик целевого метода;
-
значения аргументов nargs, где количество, тип и порядок значений должны соответствовать описателю метода в динамически вычисленной точке вызова.
Исключения при связывании
Во время разрешения символической ссылки на динамически вычисленную точку вызова могут быть выброшены любые исключения, относящиеся к разрешению динамически вычисленных точек вызова.
Примечания
Если символическая ссылка на динамически вычисленную точку вызова может быть разрешена, это означает, что не-null reference к экземпляру java.lang.invoke.CallSite привязана к инструкции invokedynamic. Следовательно, обработчик целевого метода, указанный экземпляром java.lang.invoke.CallSite, не-null.
Аналогично, успешное разрешение подразумевает, что описатель метода в символической ссылке семантически равен типу описателя обработчика целевого метода.
Вместе эти инварианты означают, что инструкция invokedynamic, привязанная к экземпляру java.lang.invoke.CallSite, никогда не выбрасывает исключение NullPointerException или java.lang.invoke.WrongMethodTypeException.
invokeinterface
Операция
Вызов метода интерфейса
Формат
invokeinterface
indexbyte1
indexbyte2
count
0
Формы
invokeinterface = 185 (0xb9)
Стек операндов
..., objectref, [arg1, [arg2 ...]] →
...
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения по указанному индексу должен быть символической ссылкой на метод интерфейса (§5.1), которая содержит имя и дескриптор (§4.3.3) метода интерфейса, а также символическую ссылку на интерфейс, в котором находится метод интерфейса. Названный метод интерфейса разрешается (§5.4.3.4).
Разрешенный метод интерфейса не должен быть методом инициализации экземпляра или методом инициализации класса или интерфейса (§2.9.1, §2.9.2).
Операнд count — это беззнаковый байт, который не должен быть равен нулю. objectref должен быть типа reference и должен следовать в стеке операндов nargs аргументами, где количество, тип и порядок значений должны соответствовать дескриптору разрешенного метода интерфейса. Значение четвертого операндного байта всегда должно быть нулевым.
Пусть C — класс objectref. Метод выбирается относительно C и разрешенного метода (§5.4.6). Это вызываемый метод.
Если вызываемый метод является synchronized, монитор, связанный с objectref, входит или повторно входит, как если бы выполнялась инструкция monitorenter (§monitorenter) в текущем потоке.
Если вызываемый метод не является native, nargs значений аргументов и objectref извлекаются из стека операндов. На стеке виртуальной машины Java создается новый кадр для вызываемого метода. objectref и значения аргументов последовательно становятся значениями локальных переменных нового кадра, при этом objectref находится в локальной переменной 0, arg1 в локальной переменной 1 (или, если arg1 имеет тип long или double, в локальных переменных 1 и 2) и так далее. Любое значение аргумента, являющееся типом с плавающей точкой, претерпевает преобразование набора значений (§2.8.3) перед хранением в локальной переменной. Затем новый кадр становится текущим, и виртуальная машина Java устанавливает значение на код первой инструкции вызываемого метода. Выполнение продолжается с первой инструкции метода.
Если вызываемый метод является native, а зависящий от платформы код, который его реализует, еще не привязан (§5.6) к виртуальной машине Java, то это делается. Значения nargs аргументов и objectref извлекаются из стека операндов и передаются как параметры коду, реализующему метод. Любое значение аргумента, являющееся типом с плавающей точкой, претерпевает преобразование набора значений (§2.8.3) перед передачей в качестве параметра. Параметры передаются, и код вызывается способом, зависящим от реализации. При возвращении зависящего от платформы кода:
-
Если метод
nativeявляетсяsynchronized, монитор, связанный с objectref, обновляется и, возможно, выходит, как если бы выполнялась инструкция monitorexit (§monitorexit) в текущем потоке. -
Если метод
nativeвозвращает значение, возвращаемое значение зависящего от платформы кода преобразуется зависящим от реализации способом в тип возврата методаnativeи помещается в стек операндов.
Исключения связывания
При разрешении символической ссылки на метод интерфейса могут быть выброшены любые исключения, связанные с разрешением метода интерфейса (§5.4.3.4).
В противном случае, если разрешенный метод является static, инструкция invokeinterface вызывает исключение IncompatibleClassChangeError.
Обратите внимание, что invokeinterface может ссылаться на методы private, объявленные в интерфейсах, включая интерфейсы-соседства.
Исключения времени выполнения
В противном случае, если objectref является null, инструкция invokeinterface вызывает исключение NullPointerException.
В противном случае, если класс objectref не реализует разрешенный интерфейс, invokeinterface вызывает исключение IncompatibleClassChangeError.
В противном случае, если выбранный метод не является public и не private, invokeinterface вызывает исключение IllegalAccessError.
В противном случае, если выбранный метод является abstract, invokeinterface вызывает исключение AbstractMethodError.
В противном случае, если выбранный метод является native и код, реализующий метод, не может быть привязан, invokeinterface вызывает исключение UnsatisfiedLinkError.
В противном случае, если метод не выбран, и существует несколько методов-суперитерфейсов максимальной специфичности C, которые соответствуют имени и дескриптору разрешенного метода и не являются abstract, invokeinterface вызывает исключение IncompatibleClassChangeError
В противном случае, если метод не выбран, и нет методов-суперитерфейсов максимальной специфичности C, которые соответствуют имени и дескриптору разрешенного метода и не являются abstract, invokeinterface вызывает исключение AbstractMethodError.
Примечания
Операнд count инструкции invokeinterface записывает количество значений аргументов, где значение аргумента типа long или типа double вносит два единицы в значение count, а аргумент любого другого типа вносит одну единицу. Эту информацию также можно получить из описателя выбранного метода. Избыточность является исторической особенностью.
Четвертый байт операнда предназначен для резервирования места для дополнительного операнда, используемого в некоторых реализациях виртуальной машины Java Oracle, которые заменяют инструкцию invokeinterface специализированной псевдоинструкцией во время выполнения. Он должен быть сохранён для обратной совместимости.
Значения аргументов nargs и objectref не являются взаимно однозначными с первыми nargs+1 локальными переменными. Значения аргументов типов long и double должны храниться в двух последовательных локальных переменных, поэтому для передачи nargs значений аргументов вызываемому методу может потребоваться больше, чем nargs локальных переменных.
Логика выбора позволяет выбрать метод, не являющийся abstract, объявленный в суперинтерфейсе. Методы в интерфейсах рассматриваются только в том случае, если в иерархии классов нет соответствующего метода. В случае, если в иерархии суперинтерфейсов есть два метода, не являющихся abstract, и ни один из них не является более конкретным, возникает ошибка; попытка избежать неоднозначности не предпринимается (например, один может быть целевым методом, а другой — не связанным, но мы не отдаём предпочтение целевому методу). С другой стороны, если существует много методов abstract, но только один метод, не являющийся abstract, выбирается метод, не являющийся abstract (если метод abstract не более конкретный).
invokespecial
Операция
Вызов экземпляра метода; прямой вызов методов инициализации экземпляра и методов текущего класса и его супертипов
Формат
invokespecial
indexbyte1
indexbyte2
Формы
invokespecial = 183 (0xb7)
Стек операндов
..., objectref, [arg1, [arg2 ...]] →
...
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Запись в постоянном пуле времени выполнения по этому индексу должна быть символической ссылкой на метод или метод интерфейса (§5.1), которая содержит имя и дескриптор (§4.3.3) метода или метода интерфейса, а также символическую ссылку на класс или интерфейс, в котором находится метод или метод интерфейса. Имя метода разрешается (§5.4.3.3, §5.4.3.4).
Если все перечисленные ниже условия верны, пусть C будет непосредственным суперклассом текущего класса:
В противном случае, пусть C будет классом или интерфейсом, указанным в символической ссылке.
Фактический вызываемый метод выбирается с помощью следующей процедуры поиска:
-
Если C содержит объявление экземпляра метода с тем же именем и дескриптором, что и разрешенный метод, то это вызываемый метод.
-
В противном случае, если C — класс и имеет суперкласс, выполняется поиск объявления экземпляра метода с тем же именем и дескриптором, что и разрешенный метод, начиная с непосредственного суперкласса C и продолжая с непосредственного суперкласса этого класса и так далее, пока не будет найдено совпадение или не останется больше суперклассов. Если совпадение найдено, то это вызываемый метод.
-
В противном случае, если C — интерфейс и класс
Objectсодержит объявлениеpublicметода экземпляра с тем же именем и дескриптором, что и разрешенный метод, то это вызываемый метод. -
В противном случае, если ровно один максимально-специфический метод (§5.4.3.3) в суперинтерфейсах C соответствует имени и дескриптору разрешенного метода и не является
abstract, то это вызываемый метод.
objectref должен иметь тип reference и должен следовать за ним в стеке операндов nargs значениями аргументов, где количество, тип и порядок значений должны соответствовать дескриптору выбранного метода экземпляра.
Если метод является synchronized, монитор, связанный с objectref, вводится или повторно вводится, как если бы выполнялась инструкция monitorenter (§monitorenter) в текущем потоке.
Если метод не native, nargs значения аргументов и objectref извлекаются из стека операндов. Для вызываемого метода создается новая рамка в стеке виртуальной машины Java. objectref и значения аргументов последовательно становятся значениями локальных переменных новой рамки, где objectref находится в локальной переменной 0, arg1 — в локальной переменной 1 (или, если arg1 имеет тип long или double, в локальных переменных 1 и 2) и так далее. Любое значение аргумента, имеющее тип с плавающей точкой, претерпевает преобразование набора значений (§2.8.3) перед сохранением в локальной переменной. Затем новая рамка становится текущей, и виртуальная машина Java устанавливает ее в код первого оператора вызываемого метода. Выполнение продолжается с первого оператора метода.
Если метод является 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.
В противном случае, если шаг 1, шаг 2 или шаг 3 процедуры поиска выбирает abstract метод, invokespecial выбрасывает AbstractMethodError.
В противном случае, если шаг 1, шаг 2 или шаг 3 процедуры поиска выбирает native метод, и код, реализующий метод, не может быть привязан, invokespecial выбрасывает UnsatisfiedLinkError.
В противном случае, если шаг 4 процедуры поиска определяет, что существует несколько максимально-специфических методов суперинтерфейса C, которые соответствуют имени и дескриптору разрешенного метода и не являются abstract, invokespecial выбрасывает IncompatibleClassChangeError
В противном случае, если шаг 4 процедуры поиска определяет, что не существует максимально-специфических методов суперинтерфейса C, которые соответствуют имени и дескриптору разрешенного метода и не являются abstract, invokespecial выбрасывает AbstractMethodError.
Примечания
Разница между инструкцией invokespecial и инструкцией invokevirtual (§invokevirtual) заключается в том, что invokevirtual вызывает метод на основе класса объекта. Инструкция invokespecial используется для прямого вызова методов инициализации экземпляров (§2.9.1), а также методов текущего класса и его супертипов.
Инструкция invokespecial именовалась invokenonvirtual до выпуска JDK 1.0.2.
Значения аргумента nargs и objectref не являются взаимно однозначным соответствием первым nargs+1 локальным переменным. Значения аргументов типов long и double должны храниться в двух последовательных локальных переменных, поэтому для передачи nargs значений аргументов вызываемому методу может потребоваться больше, чем nargs локальных переменных.
Инструкция invokespecial обрабатывает вызов метода не-abstract интерфейса, на который ссылаются либо напрямую через суперинтерфейс, либо через суперкласс. В этих случаях правила выбора в основном такие же, как и для invokeinterface (за исключением того, что поиск начинается с другого класса).
invokestatic
Операция
Вызов метода класса (static)
Формат
invokestatic
indexbyte1
indexbyte2
Формы
invokestatic = 184 (0xb8)
Оперативная область памяти
..., [arg1, [arg2 ...]] →
...
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Запись в постоянном пуле времени выполнения по этому индексу должна быть символической ссылкой на метод или метод интерфейса (§5.1), которая содержит имя и дескриптор (§4.3.3) метода или метода интерфейса, а также символическую ссылку на класс или интерфейс, в котором находится метод или метод интерфейса. Названный метод разрешается (§5.4.3.3, §5.4.3.4).
Разрешенный метод не должен быть методом инициализации экземпляра или методом инициализации класса или интерфейса (§2.9.1, §2.9.2).
Разрешенный метод должен быть static, и поэтому не может быть abstract.
При успешном разрешении метода класс или интерфейс, объявивший разрешенный метод, инициализируется, если этот класс или интерфейс ещё не был инициализирован (§5.5).
Оперативная область памяти должна содержать nargs значений аргументов, где количество, тип и порядок значений должны соответствовать дескриптору разрешенного метода.
Если метод является synchronized, монитор, связанный с разрешенным объектом Class, вводится или повторно вводится, как если бы выполнялась инструкция monitorenter (§monitorenter) в текущем потоке.
Если метод не является native, nargs значений аргументов извлекаются из оперативной области памяти. Для вызываемого метода создаётся новый кадр на стеке виртуальной машины Java. Значения аргументов nargs последовательно становятся значениями локальных переменных нового кадра, причём arg1 находится в локальной переменной 0 (или, если arg1 является типа long или double, в локальных переменных 0 и 1) и так далее. Любое значение аргумента, которое имеет тип с плавающей точкой, претерпевает преобразование набора значений (§2.8.3) перед сохранением в локальную переменную. Затем новый кадр становится текущим, а виртуальная машина Java устанавливается на код первой инструкции вызываемого метода. Выполнение продолжается с первой инструкции метода.
Если метод является 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.3), тогда инструкция invokevirtual выполняется следующим образом.
Пусть C будет классом objectref. Метод выбирается относительно C и разрешенного метода (§5.4.6). Это метод для вызова.
За objectref в стеке операндов должны следовать значения аргументов nargs, где количество, тип и порядок значений должны соответствовать дескриптору выбранного метода экземпляра.
Если вызываемый метод — synchronized, то монитор, связанный с objectref, входит или повторно входит, как если бы было выполнено инструкция monitorenter (§monitorenter) в текущем потоке.
Если вызываемый метод не native, значения аргументов nargs и objectref извлекаются из стека операндов. В стеке Java Virtual Machine создается новый кадр для вызываемого метода. objectref и значения аргументов последовательно становятся значениями локальных переменных нового кадра, с objectref в локальной переменной 0, arg1 в локальной переменной 1 (или, если arg1 имеет тип long или double, в локальных переменных 1 и 2), и так далее. Любое значение аргумента, имеющее тип с плавающей запятой, подвергается преобразованию набора значений (§2.8.3) до сохранения в локальной переменной. Затем новый кадр становится текущим, и Java Virtual Machine pc устанавливается в код первой инструкции вызываемого метода. Выполнение продолжается с первой инструкции метода.
Если вызываемый метод — native, а зависящий от платформы код, который его реализует, еще не был привязан (§5.6) в Java Virtual Machine, это делается. Значения аргументов nargs и objectref извлекаются из стека операндов и передаются в качестве параметров коду, который реализует метод. Любое значение аргумента, имеющее тип с плавающей запятой, подвергается преобразованию набора значений (§2.8.3) до передачи в качестве параметра. Параметры передаются, и код вызывается способом, зависящим от реализации. Когда код, зависящий от платформы, возвращает управление, происходит следующее:
-
Если метод
native—synchronized, то монитор, связанный с objectref, обновляется и, возможно, выходит, как если бы была выполнена инструкция monitorexit (§monitorexit) в текущем потоке. -
Если метод
nativeвозвращает значение, возвращаемое значение кода, зависящего от платформы, преобразуется способом, зависящим от реализации, в тип возвращаемого значения методаnativeи помещается в стек операндов.
Если разрешенный метод является сигнатурно полиморфным (§2.9.3), и объявлен в классе java.lang.invoke.MethodHandle, тогда инструкция invokevirtual выполняется следующим образом, где D — дескриптор метода, символьно ссылаемый инструкцией.
Сначала, reference к экземпляру java.lang.invoke.MethodType получается, как если бы путем разрешения символьной ссылки на тип метода (§5.4.3.5) с теми же типами параметров и возвращаемого значения, что и у D.
-
Если именованный метод —
invokeExact, экземплярjava.lang.invoke.MethodTypeдолжен быть семантически равен дескриптору типа принимающего обработчика методов objectref. Обработчик методов, который будет вызван — это objectref. -
Если именованный метод —
invoke, и экземплярjava.lang.invoke.MethodTypeсемантически равен дескриптору типа принимающего обработчика методов objectref, тогда обработчик методов, который будет вызван — это objectref. -
Если именованный метод —
invoke, и экземплярjava.lang.invoke.MethodTypeне семантически равен дескриптору типа принимающего обработчика методов objectref, тогда Java Virtual Machine пытается настроить дескриптор типа принимающего обработчика методов, как если бы путем вызова методаasTypeизjava.lang.invoke.MethodHandle, чтобы получить точно вызываемый обработчик методовm. Обработчик методов, который будет вызван — этоm.
За objectref в стеке операндов должны следовать значения аргументов nargs, где количество, тип и порядок значений должны соответствовать дескриптору типа вызываемого обработчика методов. (Этот дескриптор типа будет соответствовать дескриптору метода, подходящему для типа вызываемого обработчика методов, как указано в §5.4.3.5.)
Затем, если вызываемый обработчик методов имеет поведение байт-кода, Java Virtual Machine вызывает обработчик методов, как если бы путем выполнения поведения байт-кода, связанного с типом обработчика методов. Если тип — 5 (REF_invokeVirtual), 6 (REF_invokeStatic), 7 (REF_invokeSpecial), 8 (REF_newInvokeSpecial) или 9 (REF_invokeInterface), тогда кадр будет создан и сделан текущим в процессе выполнения поведения байт-кода; однако этот кадр не виден, и когда метод, вызванный поведением байт-кода, завершается (нормально или внезапно), кадр его вызывающего считается кадром для метода, содержащего эту инструкцию invokevirtual.
В противном случае, если вызываемый обработчик методов не имеет поведения байт-кода, Java Virtual Machine вызывает его способом, зависящим от реализации.
Если разрешенный метод является сигнатурно полиморфным и объявлен в классе java.lang.invoke.VarHandle, тогда инструкция invokevirtual выполняется следующим образом, где N и D — имя и дескриптор метода, символьно ссылаемого инструкцией.
Сначала, reference к экземпляру java.lang.invoke.VarHandle.AccessMode получается, как если бы путем вызова метода valueFromMethodName из java.lang.invoke.VarHandle.AccessMode с аргументом String, обозначающим N.
Во-вторых, reference к экземпляру java.lang.invoke.MethodType получается, как если бы путем вызова метода accessModeType из java.lang.invoke.VarHandle на экземпляре objectref, с экземпляром java.lang.invoke.VarHandle.AccessMode в качестве аргумента.
В-третьих, reference к экземпляру java.lang.invoke.MethodHandle получается, как если бы путем вызова метода varHandleExactInvoker из java.lang.invoke.MethodHandles с экземпляром java.lang.invoke.VarHandle.AccessMode в качестве первого аргумента и экземпляром java.lang.invoke.MethodType в качестве второго аргумента. Полученный экземпляр называется обработчиком метода вызывающего.
Наконец, значения аргументов nargs и objectref извлекаются из стека операндов, и вызывается обработчик метода вызывающего. Вызов происходит как если бы путем выполнения инструкции invokevirtual, которая указывает индекс пула констант времени выполнения на символьную ссылку R, где:
-
R — символическая ссылка на метод класса;
-
для символической ссылки на класс, в котором находится метод, R указывает
java.lang.invoke.MethodHandle; -
для имени метода, R указывает
invoke; -
для дескриптора метода, R указывает тип возвращаемого значения, указанный дескриптором возврата D, и указывает тип первого параметра
java.lang.invoke.VarHandle, за которым следуют типы параметров, указанные дескрипторами параметров D (если таковые имеются) в порядке следования.
и как будто следующие элементы были последовательно помещены на стек операндов:
-
ссылка
referenceна экземплярjava.lang.invoke.MethodHandle(дескриптор метода-вызываемого); -
objectref;
-
значения аргумента nargs, где количество, тип и порядок значений должны соответствовать типу дескриптора метода-вызываемого.
Исключения при связывании
Во время разрешения символической ссылки на метод могут быть выброшены любые исключения, связанные с разрешением методов (§5.4.3.3).
В противном случае, если разрешённый метод является методом класса (static), инструкция invokevirtual выбрасывает исключение IncompatibleClassChangeError.
В противном случае, если разрешённый метод полиморфный по сигнатуре и объявлен в классе java.lang.invoke.MethodHandle, то при разрешении типа метода, полученного из дескриптора в символической ссылке на метод, могут быть выброшены любые исключения, относящиеся к разрешению типа метода (§5.4.3.5).
В противном случае, если разрешённый метод полиморфный по сигнатуре и объявлен в классе java.lang.invoke.VarHandle, может быть выброшено любое исключение связи, которое может возникнуть при вызове дескриптора метода. Никакие исключения связи не выбрасываются при вызове методов valueFromMethodName, accessModeType и varHandleExactInvoker.
Исключения во время выполнения
В противном случае, если objectref является null, инструкция invokevirtual выбрасывает исключение NullPointerException.
В противном случае, если разрешённый метод не полиморфный по сигнатуре:
-
Если выбранный метод является
abstract, invokevirtual выбрасывает исключениеAbstractMethodError. -
В противном случае, если выбранный метод является
nativeи код, реализующий метод, не может быть привязан, invokevirtual выбрасывает исключениеUnsatisfiedLinkError. -
В противном случае, если метод не выбран, и существует несколько методов-суперинтерфейсов C с максимальной специфичностью, которые соответствуют имени и дескриптору разрешённого метода и не являются
abstract, invokevirtual выбрасывает исключениеIncompatibleClassChangeError -
В противном случае, если метод не выбран, и нет методов-суперинтерфейсов C с максимальной специфичностью, которые соответствуют имени и дескриптору разрешённого метода и не являются
abstract, invokevirtual выбрасывает исключениеAbstractMethodError.
В противном случае, если разрешённый метод полиморфный по сигнатуре и объявлен в классе java.lang.invoke.MethodHandle, то:
-
Если имя метода является
invokeExact, и полученный экземплярjava.lang.invoke.MethodTypeне равен по смыслу типу дескриптора метода-получателя objectref, инструкция invokevirtual выбрасывает исключениеjava.lang.invoke.WrongMethodTypeException. -
Если имя метода является
invoke, и полученный экземплярjava.lang.invoke.MethodTypeне является допустимым аргументом для методаasTypeклассаjava.lang.invoke.MethodHandle, вызываемого на методе-получателе objectref, инструкция invokevirtual выбрасывает исключениеjava.lang.invoke.WrongMethodTypeException.
В противном случае, если разрешённый метод полиморфный по сигнатуре и объявлен в классе java.lang.invoke.VarHandle, тогда любое исключение времени выполнения, которое может возникнуть при вызове дескриптора метода, может быть выброшено. Никакие исключения времени выполнения не выбрасываются при вызове методов valueFromMethodName, accessModeType и varHandleExactInvoker, за исключением NullPointerException, если objectref является null.
Примечания
Значения аргументов nargs и objectref не находятся в взаимно однозначном соответствии с первыми nargs+1 локальными переменными. Значения аргументов типов long и double должны храниться в двух последовательных локальных переменных, поэтому для передачи nargs значений аргументов вызываемому методу может потребоваться больше, чем nargs локальных переменных.
Возможна ситуация, когда символическая ссылка инструкции invokevirtual разрешается на метод интерфейса. В этом случае возможно, что нет переопределённого метода в иерархии классов, но соответствующий метод интерфейса, не являющийся abstract, соответствует дескриптору разрешённого метода. Логика выбора соответствует такому методу, используя те же правила, что и для invokeinterface.
ior
Операция
Побитовое ИЛИ int
Формат
ior
Формы
ior = 128 (0x80)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба value1 и value2 должны быть типа int. Они извлекаются из стека операндов. Результат result вычисляется как побитовое включительно ИЛИ value1 и value2. Результат result помещается на стек операндов.
irem
Операция
Остаток от деления int
Формат
irem
Формы
irem = 112 (0x70)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба value1 и value2 должны быть типа int. Значения извлекаются из стека операндов. Полученный int result равен value1 - (value1 / value2) * value2. result помещается на стек операндов.
Результат инструкции irem таков, что (a/b)*b
+ (a%b) равно a. Это равенство справедливо и в том частном случае, когда делимое - это отрицательное int наибольшего возможного значения для его типа, а делитель - -1 (остаток равен 0). Из этого правила следует, что результат операции вычисления остатка может быть отрицательным только если делимое отрицательно и может быть положительным только если делимое положительно. Более того, абсолютная величина результата всегда меньше абсолютной величины делителя.
Исключение во время выполнения
Если значение делителя для операции вычисления остатка int равно 0, инструкция irem генерирует исключение ArithmeticException.
ireturn
Операция
Возврат int из метода
Формат
ireturn
Формы
ireturn = 172 (0xac)
Стек операндов
..., value →
[пусто]
Описание
Текущий метод должен иметь тип возвращаемого значения boolean, byte, char, short или int. value должно быть типа int. Если текущий метод является методом synchronized, то монитор, в который был вошёл или в который был повторно вошёл поток при вызове метода, обновляется и, возможно, выходит из него так, как если бы выполнялась инструкция monitorexit (§monitorexit) в текущем потоке. Если исключение не генерируется, value извлекается из стека операндов текущей рамки (§2.6) и помещается на стек операндов рамки вызывающего метода. Любые другие значения на стеке операндов текущего метода удаляются.
Перед тем как поместить value в стек операндов рамки вызывающего метода, может потребоваться его преобразование. Если тип возвращаемого значения вызванного метода был byte, char или short, тогда value преобразуется из int в тип возвращаемого значения так, как если бы выполнялись инструкции i2b, i2c или i2s соответственно. Если тип возвращаемого значения вызываемого метода был boolean, тогда value сужается с int до boolean путём выполнения побитового AND value и 1.
Затем интерпретатор возвращает управление вызывающему методу, восстанавливая рамку вызывающего метода.
Исключения во время выполнения
Если реализация Java Virtual Machine не применяет правила структурированного блокирования, описанные в §2.11.10, то если текущий метод является методом synchronized и текущий поток не является владельцем монитора, в который было вошёл или в который был повторно вошёл поток при вызове метода, то ireturn генерирует исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит инструкцию monitorexit, но не инструкцию monitorenter для объекта, на котором метод синхронизируется.
В противном случае, если реализация Java Virtual Machine применяет правила структурированного блокирования, описанные в §2.11.10, и если первое из этих правил нарушено при вызове текущего метода, тогда ireturn генерирует исключение IllegalMonitorStateException.
ishl
Операция
Сдвиг влево int
Формат
ishl
Формы
ishl = 120 (0x78)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба value1 и value2 должны быть типа int. Значения извлекаются из стека операндов. Вычисляется int result, сдвигая value1 влево на s разрядов, где s - значение 5 младших разрядов value2. result помещается на стек операндов.
Примечания
Это эквивалентно (даже при переполнении) умножению на 2 в степени s. Используемое расстояние сдвига всегда находится в диапазоне от 0 до 31 включительно, как если бы value2 подверглось побитовому логическому AND с маской 0x1f.
ishr
Operation
Арифметический сдвиг вправо int
Format
ishr
Forms
ishr = 122 (0x7a)
Operand Stack
..., value1, value2 →
..., result
Description
Both value1 and value2 must be of type int. The values are popped from the operand stack. An int result is calculated by shifting value1 right by s bit positions, with sign extension, where s is the value of the low 5 bits of value2. The result is pushed onto the operand stack.
Notes
The resulting value is floor(value1 / 2s), where s is value2 & 0x1f. For non-negative value1, this is equivalent to truncating int division by 2 to the power s. The shift distance actually used is always in the range 0 to 31, inclusive, as if value2 were subjected to a bitwise logical AND with the mask value 0x1f.
istore
Operation
Сохранить int в локальную переменную
Format
istore
index
Forms
istore = 54 (0x36)
Operand Stack
..., value →
...
Description
The index is an unsigned byte that must be an index into the local variable array of the current frame (§2.6). The value on the top of the operand stack must be of type int. It is popped from the operand stack, and the value of the local variable at index is set to value.
Notes
The istore opcode can be used in conjunction with the wide instruction (§wide) to access a local variable using a two-byte unsigned index.
istore_<n>
Operation
Сохранить int в локальную переменную
Format
istore_<n>
Forms
istore_0 = 59 (0x3b)
istore_1 = 60 (0x3c)
istore_2 = 61 (0x3d)
istore_3 = 62 (0x3e)
Operand Stack
..., value →
...
Description
The <n> must be an index into the local variable array of the current frame (§2.6). The value on the top of the operand stack must be of type int. It is popped from the operand stack, and the value of the local variable at <n> is set to value.
Notes
Each of the istore_<n> instructions is the same as istore with an index of <n>, except that the operand <n> is implicit.
isub
Operation
Вычесть int
Format
isub
Forms
isub = 100 (0x64)
Operand Stack
..., value1, value2 →
..., result
Description
Both value1 and value2 must be of type int. The values are popped from the operand stack. The int result is value1 - value2. The result is pushed onto the operand stack.
For int subtraction, a-b produces the same result as a+(-b). For int values, subtraction from zero is the same as negation.
The result is the 32 low-order bits of the true mathematical result in a sufficiently wide two's-complement format, represented as a value of type int. If overflow occurs, then the sign of the result may not be the same as the sign of the mathematical difference of the two values.
Despite the fact that overflow may occur, execution of an isub instruction never throws a run-time exception.
iushr
Операция
Логический сдвиг вправо int
Формат
iushr
Формы
iushr = 124 (0x7c)
Стек операндов
..., value1, value2 →
..., результат
Описание
Оба 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. Они извлекаются из стека операндов. Вычисляется результат с использованием побитового исключающего ИЛИ 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)
Стек операндов
... →
..., адрес
Описание
Адрес кода инструкции, непосредственно следующей за этой инструкцией jsr_w, помещается в стек операндов как значение типа returnAddress. Беззнаковые branchbyte1, branchbyte2, branchbyte3 и branchbyte4 используются для построения знакового 32-битного смещения, где смещение равно (branchbyte1 << 24) | (branchbyte2 << 16) | (branchbyte3 << 8) | branchbyte4. Выполнение продолжается по адресу, смещённому на это значение относительно адреса инструкции jsr_w. Целевой адрес должен быть адресом кода инструкции внутри метода, содержащего инструкцию jsr_w.
Примечания
Обратите внимание, что jsr_w помещает адрес в стек операндов, а ret (§ret) извлекает его из локальной переменной. Эта асимметрия намеренная.
В реализации компилятора Oracle для языка программирования Java до Java SE 6 инструкция jsr_w использовалась с инструкцией ret при реализации finally-блока (§3.13, §4.10.2.5).
Несмотря на то, что инструкция jsr_w использует 4-байтовое смещение ветвления, другие факторы ограничивают размер метода 65535 байтами (§4.11). Это ограничение может быть увеличено в будущих версиях виртуальной машины Java.
l2d
Операция
Преобразование long в double
Формат
l2d
Формы
l2d = 138 (0x8a)
Стек операндов
..., значение →
..., результат
Описание
Значение значение вверху стека операндов должно быть типа long. Оно извлекается из стека операндов и преобразуется в double результат с использованием режима округления 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 бит значения и отбрасывания старших 32 бит. Результат помещается в стек операндов.
Примечания
Инструкция l2i выполняет сужающее преобразование примитивных типов (JLS §5.1.3). Она может потерять информацию о значении значение в целом. Результат может также иметь другой знак, чем исходное значение.
ladd
Операция
Добавить long
Формат
ladd
Формы
ladd = 97 (0x61)
Стек операндов
..., value1, value2 →
..., результат
Описание
Оба value1 и value2 должны быть типа long. Значения извлекаются из стека операндов. long результат равен value1 + value2. Результат помещается в стек операндов.
Результат — это 64 младших бита истинного математического результата в достаточно широком формате со знаком, представленного значением типа long. Если происходит переполнение, знак результата может не совпадать со знаком математической суммы двух значений.
Несмотря на возможность переполнения, выполнение инструкции ladd никогда не вызывает исключения во время выполнения.
laload
Операция
Загрузка long из массива
Формат
laload
Формы
laload = 47 (0x2f)
Стек операндов
..., arrayref, индекс →
..., значение
Описание
arrayref должен быть типа reference и должен ссылаться на массив, компоненты которого имеют тип long. Индекс должен быть типа int. Оба arrayref и индекс извлекаются из стека операндов. long значение компонента массива по индексу извлекается и помещается в стек операндов.
Исключения во время выполнения
Если arrayref является null, laload вызывает исключение NullPointerException.
В противном случае, если индекс находится за пределами границ массива, на который ссылается arrayref, инструкция laload вызывает исключение ArrayIndexOutOfBoundsException.
land
Операция
Булево И long
Формат
land
Формы
land = 127 (0x7f)
Стек операндов
..., value1, value2 →
..., результат
Описание
Оба value1 и value2 должны быть типа long. Они извлекаются из стека операндов. long результат вычисляется как побитовое И value1 и value2. Результат помещается в стек операндов.
lastore
Операция
Сохранить в long массив
Формат
lastore
Формы
lastore = 80 (0x50)
Стек операндов
..., arrayref, индекс, значение →
...
Описание
arrayref должен быть типа reference и должен ссылаться на массив, компоненты которого имеют тип long. Индекс должен быть типа int, а значение — типа long. arrayref, индекс и значение извлекаются из стека операндов. long значение сохраняется в качестве компонента массива по индексу индекс.
Исключения во время выполнения
Если arrayref является null, lastore вызывает исключение NullPointerException.
В противном случае, если индекс находится за пределами границ массива, на который ссылается arrayref, инструкция lastore вызывает исключение ArrayIndexOutOfBoundsException.
lcmp
Операция
Сравнение long
Формат
lcmp
Формы
lcmp = 148 (0x94)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа long. Они оба извлекаются из стека операндов, и выполняется сравнение целых чисел со знаком. Если значение1 больше значение2, значение 1 помещается в стек операндов. Если значение1 равно значение2, значение 0 помещается в стек операндов. Если значение1 меньше значение2, значение -1 помещается в стек операндов.
lconst_
Операция
Поместить long константу
Формат
lconst_
Формы
lconst_0 = 9 (0x9)
lconst_1 = 10 (0xa)
Стек операндов
... →
..., <l>
Описание
Поместить long константу <l> (0 или 1) в стек операндов.
ldc
Операция
Поместить элемент из пула констант во время выполнения
Формат
ldc
индекс
Формы
ldc = 18 (0x12)
Стек операндов
... →
..., значение
Описание
Индекс — это беззнаковый байт, который должен быть допустимым индексом в пуле констант во время выполнения текущего класса (§2.5.5). Элемент пула констант по индексу должен быть загружаемым (§5.1), и не должен быть ни одним из следующих:
-
Числовая константа типа
longилиdouble. -
Символическая ссылка на динамически вычисляемую константу, описание поля которой является
J(обозначающейlong) илиD(обозначающейdouble).
Если элементом пула констант является числовая константа типа int или float, то значение этой числовой константы помещается в стек операндов как int или float соответственно.
В противном случае, если элементом пула констант является строковая константа, то есть ссылка на экземпляр класса String, то значение, ссылка на этот экземпляр, помещается в стек операндов.
В противном случае, если элементом пула констант является символическая ссылка на класс или интерфейс, то указанный класс или интерфейс разрешается (§5.4.3.1) и значение, ссылка на объект, представляющий этот класс или интерфейс, помещается в стек операндов.
В противном случае, элементом пула констант является символическая ссылка на тип метода, дескриптор метода или динамически вычисляемая константа. Символическая ссылка разрешается (§5.4.3.5, §5.4.3.6) и значение, результат разрешения, помещается в стек операндов.
Исключения при связывании
Во время разрешения символической ссылки может быть сгенерировано любое исключение, относящееся к разрешению этого вида символической ссылки.
ldc_w
Операция
Положить элемент из постоянного пула времени выполнения (индекс расширенного размера)
Формат
ldc_w
indexbyte1
indexbyte2
Формы
ldc_w = 19 (0x13)
Стек операндов
... →
..., value
Описание
Беззнаковые indexbyte1 и indexbyte2 собираются в беззнаковый 16-разрядный индекс в постоянный пул времени выполнения текущего класса (§2.5.5), где значение индекса вычисляется как (indexbyte1 << 8) | indexbyte2. Индекс должен быть допустимым индексом в постоянном пуле времени выполнения текущего класса. Элемент постоянного пула времени выполнения по этому индексу должен быть загружаемым (§5.1), и не должен быть ни одним из следующих:
-
Численный константа типа
longилиdouble. -
Символическая ссылка на динамически вычисляемую константу, чьё поле описания равно
J(обозначающаяlong) илиD(обозначающаяdouble).
Если элемент постоянного пула времени выполнения — это числовая константа типа int или float, или строковая константа, то value определяется и помещается в стек операндов в соответствии с правилами для инструкции ldc.
В противном случае, элемент постоянного пула времени выполнения — это символическая ссылка на класс, интерфейс, метод, тип метода, обработчик методов или динамически вычисляемую константу. Он разрешается, и value определяется и помещается в стек операндов в соответствии с правилами для инструкции ldc.
Исключения связывания
При разрешении символической ссылки может быть выброшено любое исключение, относящееся к разрешению этого вида символической ссылки.
Примечания
Инструкция ldc_w идентична инструкции ldc (§ldc), за исключением более широкого индекса постоянного пула времени выполнения.
Инструкция ldc_w может использоваться только для помещения значения типа float, взятого из набора значений с плавающей точкой (§2.3.2), потому что константа типа float в постоянном пуле (§4.4.4) должна быть взята из набора значений с плавающей точкой.
ldc2_w
Операция
Поместить long или double из постоянного пула времени выполнения (индекс расширенного размера)
Формат
ldc2_w
indexbyte1
indexbyte2
Формы
ldc2_w = 20 (0x14)
Стек операндов
... →
..., value
Описание
Беззнаковые indexbyte1 и indexbyte2 собираются в беззнаковый 16-разрядный индекс в постоянный пул времени выполнения текущего класса (§2.5.5), где значение индекса вычисляется как (indexbyte1 << 8) | indexbyte2. Индекс должен быть допустимым индексом в постоянном пуле времени выполнения текущего класса. Элемент постоянного пула времени выполнения по этому индексу должен быть загружаемым (§5.1), и, в частности, должен быть одним из следующих:
-
Численный константа типа
longилиdouble. -
Символическая ссылка на динамически вычисляемую константу, чьё поле описания равно
J(обозначающаяlong) илиD(обозначающаяdouble).
Если элемент постоянного пула времени выполнения — это числовая константа типа long или double, то значение value этой числовой константы помещается в стек операндов как long или double, соответственно.
В противном случае, элемент постоянного пула времени выполнения — это символическая ссылка на динамически вычисляемую константу. Символическая ссылка разрешается (§5.4.3.6), и value, результат разрешения, помещается в стек операндов.
Исключения связывания
При разрешении символической ссылки на динамически вычисляемую константу может быть выброшено любое исключение, относящееся к разрешению динамически вычисляемой константы.
Примечания
Существует только версия инструкции ldc2_w с широким индексом; нет инструкции ldc2, которая помещает long или double с индексом в один байт.
Инструкция ldc2_w может использоваться только для помещения значения типа double, взятого из набора значений с двойной точностью (§2.3.2), потому что константа типа double в постоянном пуле (§4.4.5) должна быть взята из набора значений с двойной точностью.
ldiv
Операция
Деление long
Формат
ldiv
Формы
ldiv = 109 (0x6d)
Стек операндов
..., value1, value2 →
..., результат
Описание
И value1, и value2 должны быть типа long. Значения извлекаются из стека операндов. long результат — значение выражения языка программирования Java value1 / value2. Результат помещается в стек операндов.
long деление округляет к нулю; то есть частное, полученное для long значений в n / d, является long значением q, модуль которого как можно больше, при условии, что |d ⋅ q| ≤ |n|. Кроме того, q положительно, когда |n| ≥ |d| и n и d имеют одинаковый знак, но q отрицательно, когда |n| ≥ |d| и n и d имеют противоположные знаки.
Есть один особый случай, который не соответствует этому правилу: если делимое — целое отрицательное число максимального модуля для типа long, а делитель — -1, возникает переполнение, и результат равен делимому; несмотря на переполнение, в этом случае исключение не генерируется.
Исключение во время выполнения
Если значение делителя при long делении равно 0, ldiv генерирует исключение ArithmeticException.
lload
Операция
Загрузка long из локальной переменной
Формат
lload
индекс
Формы
lload = 22 (0x16)
Стек операндов
... →
..., значение
Описание
Индекс — беззнаковый байт. И индекс, и индекс+1 должны быть индексами в массиве локальных переменных текущего фрейма (§2.6). Локальная переменная по индексу должна содержать long. Значение локальной переменной по индексу помещается в стек операндов.
Примечания
Инструкцию lload можно использовать совместно с инструкцией wide (§wide) для доступа к локальной переменной с использованием двубайтного беззнакового индекса.
lload_<n>
Операция
Загрузка long из локальной переменной
Формат
lload_<n>
Формы
lload_0 = 30 (0x1e)
lload_1 = 31 (0x1f)
lload_2 = 32 (0x20)
lload_3 = 33 (0x21)
Стек операндов
... →
..., значение
Описание
И <n>, и <n>+1 должны быть индексами в массиве локальных переменных текущего фрейма (§2.6). Локальная переменная по индексу <n> должна содержать long. Значение локальной переменной по индексу <n> помещается в стек операндов.
Примечания
Каждая из инструкций lload_<n> аналогична lload с индексом <n>, за исключением того, что операнд <n> является неявным.
lmul
Операция
Умножение long
Формат
lmul
Формы
lmul = 105 (0x69)
Стек операндов
..., value1, value2 →
..., результат
Описание
И value1, и value2 должны быть типа long. Значения извлекаются из стека операндов. long результат — value1 * value2. Результат помещается в стек операндов.
Результат — 64 младших бита истинного математического результата в достаточно широком формате со знаком дополнения до двух, представленного как значение типа long. Если произойдет переполнение, знак результата может не совпадать со знаком математического умножения двух значений.
Несмотря на то, что может произойти переполнение, выполнение инструкции lmul никогда не вызывает исключение во время выполнения.
lneg
Операция
Изменить знак long
Формат
lneg
Формы
lneg = 117 (0x75)
Стек операндов
..., значение →
..., результат
Описание
Значение должно быть типа long. Оно извлекается из стека операндов. long Результат — арифметическое отрицание значения, -значение. Результат помещается в стек операндов.
Для long значений отрицание равно вычитанию из нуля. Так как Java Virtual Machine использует представление чисел в дополнительном коде, а диапазон значений в дополнительном коде не симметричен, отрицание максимального отрицательного long числа приводит к тому же самому максимальному отрицательному числу. Несмотря на то, что произошел переполнение, исключение не генерируется.
Для всех long значений x, -x равно (~x)+1.
lookupswitch
Операция
Доступ к таблице переходов по совпадению ключа и переход
Формат
lookupswitch
<0-3 байта заполнения>
defaultbyte1
defaultbyte2
defaultbyte3
defaultbyte4
npairs1
npairs2
npairs3
npairs4
match-offset pairs...
Формы
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. Они извлекаются из стека операндов. long Результат вычисляется путем побитового включительно ИЛИ value1 и value2. Результат помещается в стек операндов.
lrem
Операция
Остаток от деления long
Формат
lrem
Формы
lrem = 113 (0x71)
Стек операндов
..., value1, value2 →
..., результат
Описание
Оба value1 и value2 должны быть типа long. Значения извлекаются из стека операндов. long Результат результат вычисляется как value1 - (value1 / value2) * value2. Результат помещается в стек операндов.
Результат инструкции lrem таков, что (a/b)*b + (a%b) равно a. Это тождество справедливо даже в том частном случае, когда делимое является отрицательным long максимального возможного значения для своего типа, а делитель равен -1 (остаток равен 0). Из этого правила следует, что результат операции взятия остатка может быть отрицательным только если делимое отрицательное и может быть положительным только если делимое положительное; кроме того, абсолютная величина результата всегда меньше абсолютной величины делителя.
Исключение во время выполнения
Если значение делителя для операции взятия остатка long равно 0, lrem вызывает исключение ArithmeticException.
lreturn
Операция
Возврат long из метода
Формат
lreturn
Формы
lreturn = 173 (0xad)
Стек операндов
..., значение →
[пусто]
Описание
Текущий метод должен иметь тип возвращаемого значения 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 →
..., результат
Описание
value1 должен быть типа long, а value2 - типа int. Значения извлекаются из стека операндов. Результат результат вычисляется путем сдвига value1 влево на s позиций, где s - 6 младших битов value2. Результат помещается в стек операндов.
Примечания
Это эквивалентно (даже если происходит переполнение) умножению на 2 в степени s. Расстояние сдвига, фактически используемое, поэтому всегда находится в диапазоне от 0 до 63 включительно, как если бы value2 было подвергнуто поразрядному логическому И с маской 0x3f.
lshr
Операция
Арифметический сдвиг вправо long
Формат
lshr
Формы
lshr = 123 (0x7b)
Стек операндов
..., value1, value2 →
..., result
Описание
value1 должен быть типа long, а value2 должен быть типа int. Значения извлекаются из стека операндов. long result вычисляется путем сдвига value1 вправо на s позиций, с расширением знака, где s — это значение младших 6 бит value2. result помещается в стек операндов.
Примечания
Полученное значение — это floor(value1 / 2s), где s — это value2 & 0x3f. Для неотрицательных value1 это эквивалентно усечению long деления на 2 в степени s. Таким образом, используемое расстояние сдвига всегда находится в диапазоне от 0 до 63 включительно, как если бы value2 подвергалось побитовой логической операции И с маской 0x3f.
lstore
Операция
Сохранить long в локальную переменную
Формат
lstore
index
Формы
lstore = 55 (0x37)
Стек операндов
..., value →
...
Описание
index — это беззнаковый байт. Оба index и index+1 должны быть индексами в массиве локальных переменных текущего кадра ( §2.6). value в верхней части стека операндов должен быть типа long. Он извлекается из стека операндов, и локальные переменные в index и index+1 устанавливаются в value.
Примечания
Оператор lstore может использоваться вместе с инструкцией wide ( §wide) для доступа к локальной переменной с использованием двухбайтового беззнакового индекса.
lstore_<n>
Операция
Сохранить long в локальную переменную
Формат
lstore_<n>
Формы
lstore_0 = 63 (0x3f)
lstore_1 = 64 (0x40)
lstore_2 = 65 (0x41)
lstore_3 = 66 (0x42)
Стек операндов
..., value →
...
Описание
И <n>, и <n>+1 должны быть индексами в массиве локальных переменных текущего кадра ( §2.6). value в верхней части стека операндов должен быть типа long. Он извлекается из стека операндов, и локальные переменные в <n> и <n>+1 устанавливаются в value.
Примечания
Каждая из инструкций lstore_<n> идентична lstore с index <n>, за исключением того, что операнд <n> является неявным.
lsub
Операция
Вычесть long
Формат
lsub
Формы
lsub = 101 (0x65)
Стек операндов
..., value1, value2 →
..., result
Описание
Оба value1 и value2 должны быть типа long. Значения извлекаются из стека операндов. long result — это value1 - value2. result помещается в стек операндов.
Для long вычитания a-b дает тот же результат, что и a+(-b). Для long значений вычитание из нуля совпадает с отрицанием.
Результатом являются 64 младших бита истинного математического результата в достаточно широком формате дополнительного кода, представленном в виде значения типа long. Если происходит переполнение, то знак результата может не совпадать со знаком математической разницы между двумя значениями.
Несмотря на то, что переполнение может произойти, выполнение инструкции lsub никогда не вызывает исключение во время выполнения.
lushr
Операция
Логический сдвиг вправо long
Формат
lushr
Формы
lushr = 125 (0x7d)
Стек операндов
..., value1, value2 →
..., результат
Описание
Значение value1 должно быть типа long, а value2 — типа int. Эти значения извлекаются из стека операндов. long Значение результат вычисляется путём логического сдвига value1 вправо на s позиций со смещением нулей, где s — значение младших 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), чтобы реализовать оператор synchronized в языке программирования Java (§3.14). Инструкции monitorenter и monitorexit не используются при реализации synchronized методов, хотя они могут использоваться для обеспечения эквивалентных семантик блокировки. Вход в монитор при вызове synchronized метода и выход из монитора при его возвращении обрабатываются неявно инструкциями вызова и возврата метода Java Virtual Machine, как если бы использовались monitorenter и monitorexit.
Связь монитора с объектом может управляться различными способами, которые выходят за рамки этой спецификации. Например, монитор может быть выделен и освобожден одновременно с объектом. В качестве альтернативы, он может быть динамически выделен в момент, когда поток пытается получить эксклюзивный доступ к объекту, и освобожден в какой-либо момент позже, когда ни один поток не остаётся в мониторе для объекта.
Конструкции синхронизации языка программирования Java требуют поддержки операций с мониторами помимо входа и выхода. К ним относятся ожидание монитора (Object.wait) и уведомление других потоков, ожидающих монитора (Object.notifyAll и Object.notify). Эти операции поддерживаются в стандартном пакете java.lang, поставляемом с Java Virtual Machine. Явный поддержки этих операций отсутствует в наборе инструкций Java Virtual Machine.
monitorexit
Операция
Выход из монитора для объекта
Формат
monitorexit
Формы
monitorexit = 195 (0xc3)
Стек операндов
..., objectref →
...
Описание
objectref должен быть типа reference.
Поток, выполняющий monitorexit, должен быть владельцем монитора, связанного с экземпляром, на который ссылается objectref.
Поток уменьшает счётчик входа в монитор, связанный с objectref. Если в результате значение счётчика равно нулю, поток выходит из монитора и больше не является его владельцем. Другим потокам, ожидающим входа в монитор, разрешено попытаться это сделать.
Исключения во время выполнения
Если objectref является null, monitorexit выбрасывает NullPointerException.
В противном случае, если поток, выполняющий monitorexit, не является владельцем монитора, связанного с экземпляром, на который ссылается objectref, monitorexit выбрасывает IllegalMonitorStateException.
В противном случае, если реализация Java Virtual Machine соблюдает правила структурированного блокирования, описанные в §2.11.10, и если второе из этих правил нарушается выполнением этой инструкции monitorexit, то monitorexit выбрасывает IllegalMonitorStateException.
Примечания
Одна или несколько инструкций monitorexit могут быть использованы с инструкцией monitorenter (§monitorenter) для реализации оператора synchronized в языке программирования Java (§3.14). Инструкции monitorenter и monitorexit не используются в реализации методов synchronized, хотя они могут использоваться для обеспечения эквивалентной семантики блокировки.
Java Virtual Machine поддерживает исключения, сгенерированные внутри методов synchronized и операторов synchronized по-разному:
-
Выход из монитора при нормальном завершении метода
synchronizedобрабатывается инструкциями возврата Java Virtual Machine. Выход из монитора при внезапном завершении методаsynchronizedобрабатывается неявно инструкцией athrow Java Virtual Machine. -
Когда исключение генерируется внутри оператора
synchronized, выход из монитора, вошедшего до выполнения оператораsynchronized, достигается с помощью механизма обработки исключений Java Virtual Machine (§3.14).
multianewarray
Операция
Создание многомерного массива
Формат
multianewarray
indexbyte1
indexbyte2
dimensions
Формы
multianewarray = 197 (0xc5)
Стек операндов
..., count1, [count2, ...] →
..., arrayref
Описание
Операнд dimensions — это беззнаковый байт, который должен быть больше или равен 1. Он представляет количество измерений создаваемого массива. На стеке операндов должно быть dimensions значений. Каждое такое значение представляет количество компонентов в измерении создаваемого массива, должно быть типа int и должно быть неотрицательным. count1 — желаемая длина в первом измерении, count2 — во втором и т. д.
Все значения count извлекаются со стека операндов. Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Запись в постоянном пуле времени выполнения по этому индексу должна быть символической ссылкой на класс, массив или тип интерфейса. Названный класс, массив или тип интерфейса разрешаются (§5.4.3.1). Результирующая запись должна быть типом класса массива с размерностью, большей или равной dimensions.
Многомерный массив нового типа массива выделяется в куче, управляемой сборщиком мусора. Если какое-либо значение count равно нулю, последующие измерения не выделяются. Компоненты массива в первом измерении инициализируются подмассивами типа второго измерения и так далее. Компоненты последнего выделенного измерения массива инициализируются значением по умолчанию (§2.3, §2.4) для типа элемента типа массива. Ссылка arrayref на новый массив помещается на стек операндов.
Исключения при связывании
При разрешении символической ссылки на класс, массив или тип интерфейса могут быть сгенерированы любые исключения, описанные в §5.4.3.1.
В противном случае, если у текущего класса нет разрешения на доступ к типу элемента разрешенного класса массива, multianewarray выбрасывает IllegalAccessError.
Исключение во время выполнения
В противном случае, если какое-либо из значений dimensions на стеке операндов меньше нуля, инструкция multianewarray выбрасывает NegativeArraySizeException.
Примечания
Для создания одномерного массива может быть эффективнее использовать newarray или anewarray (§newarray, §anewarray).
Класс массива, на который ссылаются через постоянный пул времени выполнения, может иметь больше измерений, чем операнд dimensions инструкции multianewarray. В этом случае создаются только первые dimensions измерений массива.
new
Операция
Создать новый объект
Формат
new
indexbyte1
indexbyte2
Формы
new = 187 (0xbb)
Стек операндов
... →
..., objectref
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения по указанному индексу должен быть символической ссылкой на тип класса или интерфейса. Наименованный тип класса или интерфейса разрешается (§5.4.3.1) и должен привести к типу класса. Память для нового экземпляра этого класса выделяется из кучи с автоматическим сбором мусора, а переменные экземпляра нового объекта инициализируются их значениями по умолчанию (§2.3, §2.4). objectref, ссылка на экземпляр, помещается в стек операндов.
При успешном разрешении класса, он инициализируется, если он ещё не был инициализирован (§5.5).
Исключения связывания
Во время разрешения символической ссылки на тип класса или интерфейса могут быть сгенерированы исключения, описанные в §5.4.3.1.
В противном случае, если символическая ссылка на тип класса или интерфейса указывает на интерфейс или абстрактный класс, new генерирует исключение InstantiationError.
Исключение во время выполнения
В противном случае, если выполнение этой инструкции new вызывает инициализацию ссылаемого класса, new может сгенерировать исключение Error, как описано в JLS §15.9.4.
Примечания
Инструкция new не полностью создает новый экземпляр; создание экземпляра не завершается до тех пор, пока метод инициализации экземпляра (§2.9.1) не будет вызван на неуникализированном экземпляре.
newarray
Операция
Создать новый массив
Формат
newarray
atype
Формы
newarray = 188 (0xbc)
Стек операндов
..., count →
..., arrayref
Описание
count должно быть типа int. Оно извлекается из стека операндов. count представляет количество элементов создаваемого массива.
atype — код, указывающий тип создаваемого массива. Он должен принимать одно из следующих значений:
Таблица 6.5.newarray-A. Коды типов массивов
| Тип массива | atype |
|---|---|
T_BOOLEAN | 4 |
T_CHAR | 5 |
T_FLOAT | 6 |
T_DOUBLE | 7 |
T_BYTE | 8 |
T_SHORT | 9 |
T_INT | 10 |
T_LONG | 11 |
Создается новый массив, компоненты которого имеют тип atype и длину count и выделяется из кучи с автоматическим сбором мусора. Ссылка arrayref на этот новый объект массива помещается в стек операндов. Каждый из элементов нового массива инициализируется значением по умолчанию (§2.3, §2.4) для типа элемента типа массива.
Исключение во время выполнения
Если count меньше нуля, newarray генерирует исключение NegativeArraySizeException.
Примечания
В реализации Oracle Java Virtual Machine массивы типа boolean (atype равно T_BOOLEAN) хранятся как массивы 8-битных значений и обрабатываются с помощью инструкций baload и bastore (§baload, §bastore), которые также используются для доступа к массивам типа byte. Другие реализации могут реализовывать упакованные boolean массивы; инструкции baload и bastore должны по-прежнему использоваться для доступа к этим массивам.
nop
Операция
Ничего не делать
Формат
nop
Формы
nop = 0 (0x0)
Стек операндов
Без изменений
Описание
Ничего не делать.
pop
Операция
Извлечь верхнее значение из стека операндов
Формат
pop
Формы
pop = 87 (0x57)
Стек операндов
..., value →
...
Описание
Извлечь верхнее значение из стека операндов.
Инструкция pop не должна использоваться, если value не является значением вычислительного типа категории 1 (§2.11.1).
pop2
Операция
Извлечь верхнее одно или два значения из стека операндов
Формат
pop2
Формы
pop2 = 88 (0x58)
Стек операндов
Форма 1:
..., value2, value1 →
...
где каждое из value1 и value2 является значением вычислительного типа категории 1 (§2.11.1).
Форма 2:
..., value →
...
где value является значением вычислительного типа категории 2 (§2.11.1).
Описание
Извлечь верхнее одно или два значения из стека операндов.
putfield
Операция
Установить поле в объекте
Формат
putfield
indexbyte1
indexbyte2
Формы
putfield = 181 (0xb5)
Стек операндов
..., objectref, value →
...
Описание
Незнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на поле (§5.1), содержащей имя и дескриптор поля, а также символическую ссылку на класс, в котором находится поле. Ссылка на поле разрешается (§5.4.3.2).
Тип хранимого value инструкцией putfield должен соответствовать дескриптору связанного поля (§4.3.2). Если тип дескриптора поля — boolean, byte, char, short или int, то value должно быть int. Если тип дескриптора поля — float, long или double, то value должно быть float, long или double соответственно. Если тип дескриптора поля — тип ссылки, то value должно быть типа, совместимого с типом дескриптора поля (JLS §5.2). Если поле является final, оно должно быть объявлено в текущем классе, и инструкция должна находиться в методе инициализации экземпляра текущего класса (§2.9.1).
value и objectref извлекаются из стека операндов.
objectref должен быть типа reference, но не массива.
Если value типа int, а тип дескриптора поля — boolean, то value сужается путём побитового И value и 1, что даёт value'. В противном случае value преобразуется с помощью преобразования множества значений (§2.8.3), что даёт value'.
Связанное поле в objectref устанавливается в value'.
Исключения при связывании
Во время разрешения символической ссылки на поле могут быть выброшены исключения, относящиеся к разрешению поля (§5.4.3.2).
В противном случае, если разрешенное поле — static поле, putfield выбрасывает IncompatibleClassChangeError.
В противном случае, если разрешенное поле — final, оно должно быть объявлено в текущем классе, и инструкция должна находиться в методе инициализации экземпляра текущего класса. В противном случае, выбрасывается IllegalAccessError.
Исключение во время выполнения
В противном случае, если objectref — null, инструкция putfield выбрасывает NullPointerException.
putstatic
Операция
Установить статическое поле в классе
Формат
putstatic
indexbyte1
indexbyte2
Формы
putstatic = 179 (0xb3)
Стек операндов
..., значение →
...
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на поле (§5.1), которая содержит имя и дескриптор поля, а также символическую ссылку на класс или интерфейс, в котором находится поле. Ссылка на поле разрешается (§5.4.3.2).
При успешном разрешении поля, класс или интерфейс, объявивший разрешенное поле, инициализируется, если этот класс или интерфейс еще не инициализированы (§5.5).
Тип значения значение, хранящегося инструкцией putstatic, должен быть совместим с дескриптором сославшегося поля (§4.3.2). Если тип дескриптора поля равен boolean, byte, char, short или int, то значение должно быть int. Если тип дескриптора поля равен float, long или double, то значение должно быть float, long или double соответственно. Если тип дескриптора поля — тип ссылки, то значение должно быть типа, совместимого с типом дескриптора поля (JLS §5.2). Если поле является final, оно должно быть объявлено в текущем классе или интерфейсе, а инструкция должна выполняться в методе инициализации класса или интерфейса текущего класса или интерфейса (§2.9.2).
Значение значение извлекается из стека операндов.
Если значение типа int, а тип дескриптора поля — boolean, то значение значение сужается, беря битовую И от значение и 1, в результате получая значение'. В противном случае значение претерпевает преобразование набора значений (§2.8.3), в результате получая значение'.
Ссылка на поле в классе или интерфейсе устанавливается в значение'.
Исключения при связывании
Во время разрешения символической ссылки на поле класса или интерфейса могут быть выброшены любые исключения, относящиеся к разрешению поля (§5.4.3.2).
В противном случае, если разрешенное поле не является полем класса (класс) или полем интерфейса, putstatic выбрасывает исключение IncompatibleClassChangeError.
В противном случае, если разрешенное поле является final, оно должно быть объявлено в текущем классе или интерфейсе, а инструкция должна выполняться в методе инициализации класса или интерфейса текущего класса или интерфейса. В противном случае выбрасывается исключение IllegalAccessError.
Исключение во время выполнения
В противном случае, если выполнение этой инструкции putstatic вызывает инициализацию ссылающегося класса или интерфейса, putstatic может выбросить исключение Error, как подробно описано в §5.5.
Примечания
Инструкция putstatic может быть использована только для установки значения поля интерфейса при инициализации этого поля. К полям интерфейса можно получить доступ только один раз при выполнении выражения инициализации переменной интерфейса во время инициализации интерфейса (§5.5, JLS §9.3.1).
ret
Операция
Возврат из подпрограммы
Формат
ret
index
Формы
ret = 169 (0xa9)
Стек операндов
Без изменений
Описание
index — беззнаковый байт от 0 до 255 включительно. Локальная переменная по индексу index в текущем фрейме (§2.6) должна содержать значение типа returnAddress. Содержимое локальной переменной записывается в регистр pc виртуальной машины Java, и выполнение продолжается там.
Примечания
Обратите внимание, что jsr (§jsr) помещает адрес в стек операндов, а ret извлекает его из локальной переменной. Такая асимметрия является намеренной.
В реализации компайлера Oracle для языка программирования Java до Java SE 6 инструкция ret использовалась с инструкциями jsr и jsr_w (§jsr, §jsr_w) в реализации блока finally (§3.13, §4.10.2.5).
Не путайте инструкцию ret с инструкцией return (§return). Инструкция return возвращает управление из метода вызывающему методу, не передавая никакого значения обратно вызывающему методу.
Код операции ret может использоваться вместе с инструкцией wide (§wide), чтобы получить доступ к локальной переменной, используя двубайтный беззнаковый индекс.
return
Операция
Возврат значения void из метода
Формат
return
Формы
return = 177 (0xb1)
Стек операндов
... →
[пустой]
Описание
Текущий метод должен иметь тип возвращаемого значения void. Если текущий метод является методом synchronized, монитор, введённый или повторно введённый при вызове метода, обновляется и, возможно, выходит, как если бы был выполнен оператор monitorexit (§monitorexit) в текущем потоке. Если исключение не выбрасывается, все значения в стеке операндов текущей рамки (§2.6) удаляются.
Затем интерпретатор возвращает управление вызывающему методу, восстанавливая кадр вызывающего метода.
Исключения во время выполнения
Если реализация Java Virtual Machine не выполняет правила структурированного блокирования, описанные в §2.11.10, то если текущий метод является методом synchronized, и текущий поток не является владельцем монитора, введённого или повторно введённого при вызове метода, то return выбрасывает исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит оператор monitorexit, но не оператор monitorenter, для объекта, для которого метод является synchronized.
В противном случае, если реализация Java Virtual Machine выполняет правила структурированного блокирования, описанные в §2.11.10, и если первое из этих правил нарушается во время вызова текущего метода, то return выбрасывает исключение IllegalMonitorStateException.
saload
Операция
Загрузка значения short из массива
Формат
saload
Формы
saload = 53 (0x35)
Стек операндов
..., arrayref, index →
..., value
Описание
arrayref должен быть типа reference и должен ссылаться на массив, компоненты которого имеют тип short. index должен быть типа int. Оба arrayref и index извлекаются из стека операндов. Извлекается компонент массива по index и расширяется со знаком до int value. Это value помещается в стек операндов.
Исключения во время выполнения
Если arrayref является null, то saload выбрасывает исключение NullPointerException.
В противном случае, если index выходит за пределы массива, на который ссылается arrayref, то инструкция saload выбрасывает исключение ArrayIndexOutOfBoundsException.
sastore
Операция
Запись в массив short
Формат
sastore
Формы
sastore = 86 (0x56)
Стек операндов
..., arrayref, index, value →
...
Описание
arrayref должен быть типа reference и должен ссылаться на массив, компоненты которого имеют тип short. Оба index и value должны быть типа int. arrayref, index и value извлекаются из стека операндов. Значение value с усечением со знаком преобразуется в short и сохраняется в качестве компонента массива с индексом index.
Исключения во время выполнения
Если arrayref является null, то sastore выбрасывает исключение NullPointerException.
В противном случае, если index выходит за пределы массива, на который ссылается arrayref, то инструкция sastore выбрасывает исключение ArrayIndexOutOfBoundsException.
sipush
Операция
Поместить short
Формат
sipush
byte1
byte2
Формы
sipush = 17 (0x11)
Стек операндов
... →
..., value
Описание
Непосредственные значения byte1 и byte2 собираются в промежуточное short, где значение short равно (byte1 << 8) | byte2. Промежуточное значение затем расширяется со знаком до int value. Это value помещается в стек операндов.
swap
Операция
Меняет местами верхние два значения стека операндов
Формат
swap
Формы
swap = 95 (0x5f)
Стек операндов
..., value2, value1 →
..., value1, value2
Описание
Меняет местами верхние два значения в стеке операндов.
Инструкцию swap нельзя использовать, если value1 и value2 не являются значениями вычислительного типа категории 1 (§2.11.1).
Примечания
Виртуальная машина Java не предоставляет инструкцию для обмена операндами вычислительных типов категории 2.
tableswitch
Операция
Обращается к таблице переходов по индексу и переходит
Формат
tableswitch
<0-3 байта заполнителя>
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. Знакомещенные 32-битные смещения интерпретируются как таблица переходов с нулевой базой. Каждое из этих знакомещенных 32-битных значений строится как (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4.
индекс должен быть типа int и извлекается из стека операндов. Если индекс меньше low или индекс больше high, то адрес назначения рассчитывается, добавляя default к адресу кода операции этой инструкции tableswitch. В противном случае извлекается смещение в позиции индекс - low таблицы переходов. Адрес назначения рассчитывается, добавляя это смещение к адресу кода операции этой инструкции tableswitch. Выполнение затем продолжается в адресе назначения.
Адрес назначения, который может быть рассчитан по каждому смещению в таблице переходов, а также по default, должен быть адресом кода операции инструкции внутри метода, содержащего эту инструкцию tableswitch.
Примечания
Требование выравнивания 4-байтовых операндов инструкции tableswitch гарантирует выравнивание этих операндов по 4 байтам только в том случае, если метод, содержащий tableswitch, начинается на границе 4 байтов.
wide
Операция
Увеличить индекс локальной переменной на дополнительные байты
Формат 1
wide
<opcode>
indexbyte1
indexbyte2
где <opcode> является одним из iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore или ret
Формат 2
wide
iinc
indexbyte1
indexbyte2
constbyte1
constbyte2
Формы
wide = 196 (0xc4)
Стек операндов
Такой же, как в изменённой инструкции
Описание
Инструкция wide изменяет поведение другой инструкции. Она принимает один из двух форматов, в зависимости от изменяемой инструкции. Первый формат инструкции wide изменяет одну из инструкций iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore или ret (§iload, §fload, §aload, §lload, §dload, §istore, §fstore, §astore, §lstore, §dstore, §ret). Второй формат применяется только к инструкции iinc (§iinc).
В обоих случаях за кодом самого оператора wide в скомпилированном коде следует код инструкции, которую wide модифицирует. В любом формате за изменённым оператором следуют два беззнаковых байта indexbyte1 и indexbyte2, которые собираются в 16-битный беззнаковый индекс локальной переменной в текущей области видимости (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Вычисленный индекс должен соответствовать индексу в массиве локальных переменных текущей области видимости. При модификации инструкции lload, dload, lstore или dstore индекс, следующий за вычисленным индексом (индекс + 1), также должен соответствовать индексу в массиве локальных переменных. Во втором формате два беззнаковых байта constbyte1 и constbyte2 следуют за indexbyte1 и indexbyte2 в потоке кода. Эти байты также собираются в знаковый 16-битный константный, где константа равна (constbyte1 << 8) | constbyte2.
Расширенный байт-код работает как обычно, за исключением использования более широкого индекса и, в случае второго формата, более широкого диапазона инкрементов.
Примечания
Хотя мы говорим, что wide "изменяет поведение другой инструкции", инструкция wide фактически обрабатывает байты, составляющие изменённую инструкцию, как операнды, изменяя встроенную инструкцию в процессе. В случае изменённой инструкции iinc, один из логических операндов iinc даже не находится в обычном смещении от оператора. Встроенная инструкция никогда не должна выполняться напрямую; её оператор никогда не должен быть целью никакой инструкции управления потоком.
© Oracle and/or its affiliates. All rights reserved.
Licensed under the Oracle Technology Network License Agreement.