Глава 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 8 и Спецификации виртуальной машины Java, издание Java SE 8.
Помимо кодов операций инструкций, указанных позднее в этой главе, которые используются в файлах class (§4 (Формат файла class)), три кода операций зарезервированы для внутреннего использования реализацией виртуальной машины 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 сохраняется как компонент массива по index.
Во время выполнения тип value должен быть совместим с типом компонентов массива, на который ссылается arrayref. В частности, присваивание значения типа ссылки S (источник) компоненту массива типа ссылки T (цель) разрешается только при соблюдении следующих условий:
-
Если S — тип класса, то:
-
Если T — тип класса, то S должен быть таким же классом, как T, или S должен быть подклассом T;
-
Если T — тип интерфейса, то S должен реализовывать интерфейс T.
-
- ... (остальные пункты перевода аналогично)
Исключения во время выполнения
... (остальной перевод аналогично)
aconst_null
Операция
Положить null
Формат
aconst_null
Формы
aconst_null = 1 (0x1)
Стек операндов
...
..., null
Описание
Поместить объект null reference на стек операндов.
Примечания
Виртуальная машина Java не предписывает конкретное значение для null.
aload
Операция
Загрузка reference из локальной переменной
Формат
aload
index
Формы
aload = 25 (0x19)
Стек операндов
... →
..., objectref
Описание
index — это беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по index должна содержать reference. Ссылка на объект objectref в локальной переменной по index помещается в стек операндов.
Примечания
Инструкция aload не может использоваться для загрузки значения типа returnAddress из локальной переменной в стек операндов. Эта асимметрия с инструкцией astore (§astore) намеренная.
Операция aload может быть использована совместно с инструкцией wide (§wide) для доступа к локальной переменной с помощью двубайтного беззнакового индекса.
aload_<n>
Операция
Загрузка reference из локальной переменной
Формат
aload_<n>
Формы
aload_0 = 42 (0x2a)
aload_1 = 43 (0x2b)
aload_2 = 44 (0x2c)
aload_3 = 45 (0x2d)
Стек операндов
... →
..., objectref
Описание
<n> должно быть индексом в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по <n> должна содержать reference. Ссылка на объект objectref в локальной переменной по <n> помещается в стек операндов.
Примечания
Инструкция aload_<n> не может использоваться для загрузки значения типа returnAddress из локальной переменной в стек операндов. Эта асимметрия с соответствующей инструкцией astore_<n> (§astore_<n>) намеренная.
Каждая из инструкций aload_<n> аналогична инструкции aload с индексом <n>, за исключением того, что операнд <n> является неявным.
anewarray
Операция
Создание нового массива reference
Формат
anewarray
indexbyte1
indexbyte2
Формы
anewarray = 189 (0xbd)
Стек операндов
..., count →
..., arrayref
Описание
count должен быть типа int. Он извлекается из стека операндов. count представляет количество компонентов создаваемого массива. Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения по этому индексу должен быть символьной ссылкой на класс, массив или тип интерфейса. Указанный класс, массив или тип интерфейса разрешаются (§5.4.3.1). Создается новый массив с компонентами этого типа длиной count из кучи сборки мусора, и ссылка на новый объект массива arrayref помещается в стек операндов. Все компоненты нового массива инициализируются значением по умолчанию для типов reference (§2.4).
Исключения связывания
Во время разрешения символьной ссылки на класс, массив или тип интерфейса могут быть выброшены исключения, описанные в §5.4.3.1.
Исключения времени выполнения
В противном случае, если count меньше нуля, инструкция anewarray выбросит исключение NegativeArraySizeException.
Примечания
Инструкция anewarray используется для создания одномерного массива ссылок на объекты или части многомерного массива.
areturn
Операция
Возврат значения reference из метода
Формат
areturn
Формы
areturn = 176 (0xb0)
Стек операндов
..., objectref →
[пустой]
Описание
objectref должен быть типа reference и должен ссылаться на объект типа, совместимого с типом, представленным дескриптором возврата (§4.3.3) текущего метода. Если текущий метод является методом synchronized, монитор, в который вошли или в который повторно вошли при вызове метода, обновляется и, возможно, выходит из него так, как будто выполняется инструкция monitorexit (§monitorexit) в текущем потоке. Если исключение не сгенерировано, objectref извлекается из стека операндов текущей рамки (§2.6) и помещается в стек операндов рамки вызывающего метода. Все другие значения в стеке операндов текущего метода удаляются.
Затем интерпретатор восстанавливает рамку вызывающего метода и возвращает управление вызывающему методу.
Исключения во время выполнения
Если реализация Java Virtual Machine не выполняет правила структурированной блокировки, описанные в §2.11.10, то если текущий метод является методом synchronized, а текущий поток не является владельцем монитора, в который вошли или в который повторно вошли при вызове метода, то areturn генерирует исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит инструкцию monitorexit, но не инструкцию monitorenter, для объекта, на котором синхронизируется метод.
В противном случае, если реализация Java Virtual Machine выполняет правила структурированной блокировки, описанные в §2.11.10, и если первое из этих правил нарушается во время вызова текущего метода, то areturn генерирует исключение IllegalMonitorStateException.
arraylength
Операция
Получение длины массива
Формат
arraylength
Формы
arraylength = 190 (0xbe)
Стек операндов
..., arrayref →
..., length
Описание
arrayref должен быть типа reference и должен ссылаться на массив. Он извлекается из стека операндов. Определяется длина length этого массива. Эта длина length помещается в стек операндов как значение типа int.
Исключения во время выполнения
Если arrayref является null, инструкция arraylength генерирует исключение NullPointerException.
astore
Операция
Сохранение reference в локальную переменную
Формат
astore
index
Формы
astore = 58 (0x3a)
Стек операндов
..., objectref →
...
Описание
index — это беззнаковый байт, который должен быть индексом в массив локальных переменных текущей рамки (§2.6). objectref вверху стека операндов должен быть типа returnAddress или типа reference. Он извлекается из стека операндов, а значение локальной переменной в позиции index устанавливается в objectref.
Примечания
Инструкция astore используется с objectref типа returnAddress при реализации условия finally языка программирования Java (§3.13).
Инструкция aload (§aload) не может быть использована для загрузки значения типа returnAddress из локальной переменной в стек операндов. Эта асимметрия с инструкцией astore является намеренной.
Код операции astore может быть использован в сочетании с инструкцией wide (§wide) для доступа к локальной переменной, используя двубайтовый беззнаковый индекс.
astore_
Операция
Сохранение 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 извлекаются из стека операндов. Значение byte value в компоненте массива по индексу index извлекается, расширяется со знаком до int value и помещается на вершину стека операндов.
Исключения во время выполнения
Если arrayref является null, то baload генерирует исключение NullPointerException.
В противном случае, если index выходит за пределы массива, на который ссылается arrayref, инструкция baload генерирует исключение ArrayIndexOutOfBoundsException.
Примечания
Инструкция baload используется для загрузки значений из массивов byte и boolean. В реализации Oracle's Java Virtual Machine, массивы boolean, то есть массивы типа T_BOOLEAN (§2.2, §newarray) реализуются как массивы 8-битных значений. Другие реализации могут реализовывать упакованные массивы boolean; инструкция baload таких реализаций должна использоваться для доступа к этим массивам.
bastore
Операция
Сохранение в массив byte или boolean
Формат
bastore
Формы
bastore = 84 (0x54)
Стек операндов
..., arrayref, index, value →
...
Описание
arrayref должен быть типа reference и должен ссылаться на массив, компоненты которого являются типа byte или типа boolean. index и value должны быть типа int. arrayref, index и value извлекаются из стека операндов. Значение int value усекается до byte и сохраняется как компонент массива по индексу index.
Исключения во время выполнения
Если arrayref является null, то bastore генерирует исключение NullPointerException.
В противном случае, если index выходит за пределы массива, на который ссылается arrayref, инструкция bastore генерирует исключение ArrayIndexOutOfBoundsException.
Примечания
Инструкция bastore используется для сохранения значений в массивах byte и boolean. В реализации Oracle's Java Virtual Machine, массивы boolean, то есть массивы типа T_BOOLEAN (§2.2, §newarray) реализуются как массивы 8-битных значений. Другие реализации могут реализовывать упакованные массивы boolean; в таких реализациях инструкция bastore должна уметь сохранять значения boolean в упакованные массивы boolean, а также значения byte в массивы byte.
bipush
Операция
Поместить byte
Формат
bipush
byte
Формы
bipush = 16 (0x10)
Стек операндов
... →
..., value
Описание
Непосредственный byte расширяется со знаком до int value. Это value помещается в стек операндов.
caload
Операция
Загрузка char из массива
Формат
caload
Формы
caload = 52 (0x34)
Стек операндов
..., arrayref, index →
..., value
Описание
arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип char. index должен быть типа int. Оба arrayref и index извлекаются из стека операндов. Компонент массива по индексу index извлекается и расширяется до знака int в value. Это value помещается в стек операндов.
Исключения во время выполнения
Если arrayref является null, caload генерирует исключение NullPointerException.
В противном случае, если index выходит за пределы массива, на который ссылается arrayref, инструкция caload генерирует исключение ArrayIndexOutOfBoundsException.
castore
Операция
Запись в массив char
Формат
castore
Формы
castore = 85 (0x55)
Стек операндов
..., arrayref, index, value →
...
Описание
arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип char. index и value должны быть типа int. arrayref, index и value извлекаются из стека операндов. Значение value усекается до char и сохраняется как компонент массива по индексу index.
Исключения во время выполнения
Если arrayref является null, castore генерирует исключение NullPointerException.
В противном случае, если index выходит за пределы массива, на который ссылается arrayref, инструкция castore генерирует исключение ArrayIndexOutOfBoundsException.
checkcast
Операция
Проверка, является ли объект заданного типа
Формат
checkcast
indexbyte1
indexbyte2
Формы
checkcast = 192 (0xc0)
Стек операндов
..., objectref →
..., objectref
Описание
objectref должен быть типа reference. Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на класс, массив или тип интерфейса.
Если objectref равен null, то стек операндов не изменяется.
В противном случае, указанный класс, массив или тип интерфейса разрешаются (§5.4.3.1). Если objectref может быть приведён к типу решённого класса, массива или интерфейса, то стек операндов не изменяется; в противном случае, инструкция checkcast вызывает исключение ClassCastException.
Следующие правила используются для определения того, может ли objectref, который не является null, быть приведён к решённому типу: если S — класс объекта, на который указывает objectref, и T — решённый класс, массив или тип интерфейса, checkcast определяет, может ли objectref быть приведён к типу T следующим образом:
-
Если S — обычный (немассивноый) класс, то:
-
Если T — тип класса, то S должен быть таким же классом, как T, или S должен быть подклассом T;
-
Если T — тип интерфейса, то S должен реализовывать интерфейс T.
-
-
Если S — тип интерфейса, то:
-
Если T — тип класса, то T должен быть
Object. -
Если T — тип интерфейса, то T должен быть тем же интерфейсом, что и S, или суперинтерфейсом S.
-
-
Если S — класс, представляющий тип массива SC
[], то есть массив компонентов типа SC, то:-
Если T — тип класса, то T должен быть
Object. -
Если T — тип интерфейса, то T должен быть одним из интерфейсов, реализуемых массивами (JLS §4.10.3).
-
Если T — тип массива TC
[], то есть массив компонентов типа TC, то одно из следующих утверждений должно быть истинным:-
TC и SC — один и тот же примитивный тип.
-
TC и SC — типы ссылок, и тип SC может быть приведён к TC путём рекурсивного применения этих правил.
-
-
Исключения связывания
Во время разрешения символической ссылки на класс, массив или тип интерфейса могут быть вызваны исключения, описанные в §5.4.3.1.
Исключение во время выполнения
В противном случае, если objectref не может быть приведён к решённому классу, массиву или типу интерфейса, инструкция checkcast вызывает исключение ClassCastException.
Примечания
Инструкция checkcast очень похожа на инструкцию instanceof (§instanceof). Они отличаются обработкой null, поведением при неудачном тесте (checkcast вызывает исключение, instanceof выталкивает код результата) и влиянием на стек операндов.
d2f
Операция
Преобразование double в float
Формат
d2f
Формы
d2f = 144 (0x90)
Стек операндов
..., value →
..., result
Описание
value на вершине стека операндов должен быть типа double. Он извлекается из стека операндов и подвергается преобразованию набора значений (§2.8.3), в результате чего получается value'. Затем value' преобразуется в результат типа float, используя режим округления IEEE 754 до ближайшего значения. Результат result помещается в стек операндов.
Когда инструкция d2f является FP-строгой (§2.8.2), результат преобразования всегда округляется до ближайшего представимого значения в наборе значений типа float (§2.3.2).
Когда инструкция d2f не является FP-строгой, результат преобразования может быть взят из множества значений с расширенным порядком значащих разрядов (§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 требует поддержки постепенного подпорогового значения, как определено в IEEE 754. Несмотря на то, что переполнение, подпороговое значение или потеря точности могут произойти, выполнение инструкции dadd никогда не вызывает исключение времени выполнения.
daload
Операция
Загрузка значения из массива
Формат
daload
Формы
daload = 49 (0x31)
Стек операндов
..., arrayref, index →
..., value
Описание
arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип double. index должен быть типа int. И arrayref, и index извлекаются из стека операндов. Значение в компоненте массива по индексу index помещается в стек операндов.
Исключения во время выполнения
Если arrayref является null, то daload выбрасывает исключение NullPointerException.
В противном случае, если index выходит за пределы массива, ссылаемого на arrayref, то инструкция daload выбрасывает исключение ArrayIndexOutOfBoundsException.
dastore
Операция
Сохранение значения в массив
Формат
dastore
Формы
dastore = 82 (0x52)
Стек операндов
..., arrayref, index, value →
...
Описание
arrayref должен быть типа reference и ссылаться на массив, компоненты которого имеют тип double. index должен быть типа int, а value должен быть типа double. arrayref, index и value извлекаются из стека операндов. Значение value преобразуется в value' (§2.8.3), и сохраняется в компоненте массива с индексом index.
Исключения во время выполнения
Если arrayref является null, то dastore выбрасывает исключение NullPointerException.
В противном случае, если index выходит за пределы массива, ссылаемого на arrayref, то инструкция dastore выбрасывает исключение ArrayIndexOutOfBoundsException.
dcmp<op>
Операция
Сравнение double
Формат
dcmp<op>
Формы
dcmpg = 152 (0x98)
dcmpl = 151 (0x97)
Стек операндов
..., value1, value2 →
..., result
Описание
value1 и value2 должны быть типа double. Значения извлекаются из стека операндов и преобразуются в value1' и value2' (§2.8.3). Выполняется сравнение с плавающей точкой:
-
Если value1' больше value2', на стек операндов помещается значение 1.
-
Если value1' равно value2', на стек операндов помещается значение 0.
-
Если value1' меньше value2', на стек операндов помещается значение -1.
-
В противном случае, по крайней мере, одно из value1' или value2' является NaN. Инструкция dcmpg помещает на стек операндов значение 1, а dcmpl - значение -1.
Сравнение с плавающей точкой выполняется в соответствии с IEEE 754. Все значения, кроме NaN, упорядочены, с отрицательной бесконечностью, меньшей всех конечных значений, и положительной бесконечностью, большей всех конечных значений. Положительный ноль и отрицательный ноль считаются равными.
Примечания
Инструкции dcmpg и dcmpl отличаются только обработкой сравнения, включающего NaN. NaN неупорядочено, поэтому любое сравнение, если один или оба операнда являются NaN, терпит неудачу. Использование как dcmpg, так и dcmpl позволяет компилятору обеспечить одно и то же значение результата в стеке операндов, независимо от того, сравнение потерпело неудачу на значениях, отличных от NaN, или потерпело неудачу из-за встречи с NaN. Для получения дополнительной информации см. §3.5.
dconst_<d>
Операция
Помещение значения double
Формат
dconst_<d>
Формы
dconst_0 = 14 (0xe)
dconst_1 = 15 (0xf)
Стек операндов
... →
..., <d>
Описание
Помещение константы <d> (0.0 или 1.0) на стек операндов.
ddiv
Операция
Деление
Формат
ddiv
Формы
ddiv = 111 (0x6f)
Стек операндов
..., value1, value2 →
..., результат
Описание
Оба value1 и value2 должны быть типа double. Значения извлекаются из стека операндов и подвергаются преобразованию типов (§2.8.3), в результате чего получаются value1' и value2'. double результат равен 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)
Стек операндов
... →
..., значение
Описание
index — это целое беззнаковое число байт. index и index+1 должны быть индексами в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу index должна содержать double. Значение локальной переменной по индексу index помещается в стек операндов.
Примечания
Инструкция dload может быть использована в сочетании с инструкцией wide (§wide) для доступа к локальной переменной с использованием двухбайтового беззнакового индекса.
dload_<n>
Операция
Загрузка double из локальной переменной
Формат
dload_<n>
Формы
dload_0 = 38 (0x26)
dload_1 = 39 (0x27)
dload_2 = 40 (0x28)
dload_3 = 41 (0x29)
Стек операндов
... →
..., значение
Описание
<n> и <n>+1 должны быть индексами в массиве локальных переменных текущей рамки (§2.6). Локальная переменная по индексу <n> должна содержать double. Значение локальной переменной по индексу <n> помещается в стек операндов.
Примечания
Каждая из инструкций dload_<n> эквивалентна инструкции dload с index равным <n>, за исключением того, что операнд <n> неявный.
dmul
Операция
Умножение double
Формат
dmul
Формы
dmul = 107 (0x6b)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа double. Значения извлекаются из стека операндов и преобразуются согласно правилам преобразования наборов значений (§2.8.3), в результате получаются значение1' и значение2'. double результат равен значение1' * значение2'. Значение результат помещается в стек операндов.
Результат инструкции dmul регулируется правилами арифметики IEEE:
-
Если значение1' или значение2' равно NaN, результат равен NaN.
-
Если ни значение1', ни значение2' не равно NaN, знак результата положителен, если оба значения имеют одинаковый знак, и отрицателен, если знаки разные.
-
Умножение бесконечности на ноль приводит к NaN.
-
Умножение бесконечности на конечное значение приводит к знакомой бесконечности, согласно правилу определения знака.
-
В остальных случаях, когда не участвуют бесконечность или NaN, произведение вычисляется и округляется до ближайшего представимого значения с использованием режима округления IEEE 754 до ближайшего. Если модуль слишком большой для представления в качестве
double, мы говорим, что операция переполняется; результат тогда является бесконечностью соответствующего знака. Если модуль слишком мал для представления в качествеdouble, мы говорим, что операция переполняется; результат тогда равен нулю соответствующего знака.
Java Virtual Machine требует поддержки постепенного переполнения, как определено в IEEE 754. Несмотря на то, что может произойти переполнение, переполнение или потеря точности, выполнение инструкции dmul никогда не вызывает исключение во время выполнения.
dneg
Операция
Изменение знака double
Формат
dneg
Формы
dneg = 119 (0x77)
Стек операндов
..., значение →
..., результат
Описание
Значение должно быть типа double. Оно извлекается из стека операндов и преобразуется согласно правилам преобразования наборов значений (§2.8.3), в результате получаем значение'. double результат является арифметическим отрицанием значение'. результат помещается в стек операндов.
Для double значений отрицание не равно вычитанию из нуля. Если x является +0.0, тогда 0.0-x равно +0.0, но -x равно -0.0. Унарный минус просто изменяет знак double.
Особые случаи:
-
Если операнд равен NaN, результат равен NaN (вспомните, что NaN не имеет знака).
-
Если операнд является бесконечностью, результат — бесконечность противоположного знака.
-
Если операнд равен нулю, результат — ноль противоположного знака.
drem
Операция
Остаток double
Формат
drem
Формы
drem = 115 (0x73)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа double. Значения извлекаются из стека операндов и подвергаются преобразованию типа (§2.8.3), что приводит к значение1' и значение2'. Результат вычисляется и помещается в стек операндов как double.
Результат инструкции drem не совпадает с результатом так называемой операции вычисления остатка, определенной в IEEE 754. Операция вычисления остатка в IEEE 754 вычисляет остаток от округленного деления, а не от усеченного деления, и поэтому ее поведение не аналогично поведению обычного целочисленного оператора остатка. Вместо этого виртуальная машина Java определяет drem так, чтобы она вела себя аналогично целочисленным инструкциям остатка виртуальной машины Java (irem и lrem); это можно сравнить с функцией C-библиотеки fmod.
Результат инструкции drem регулируется следующими правилами:
-
Если значение1' или значение2' равно NaN, результат равен NaN.
-
Если ни значение1' ни значение2' не равны NaN, знак результата равен знаку делимого.
-
Если делимое является бесконечностью или делитель является нулём, или оба, результат равен NaN.
-
Если делимое является конечным, а делитель — бесконечностью, результат равен делимому.
-
Если делимое равно нулю, а делитель конечен, результат равен делимому.
-
В остальных случаях, когда ни один из операндов не является бесконечностью, нулём или NaN, остаток с плавающей точкой результат от делимого значение1' и делителя значение2' определяется математическим соотношением результат = значение1' - (значение2' * q), где q — целое число, которое отрицательно только если значение1' / значение2' отрицательно, и положительно только если значение1' / значение2' положительно, и его величина максимальна, не превышая величины истинного математического частного значение1' и значение2'.
Несмотря на то, что может произойти деление на ноль, при вычислении инструкции drem никогда не возникает исключения во время выполнения. Переполнение, недополнение или потеря точности невозможны.
Примечания
Операцию вычисления остатка IEEE 754 можно вычислить с помощью библиотечной процедуры Math.IEEEremainder.
dreturn
Операция
Возврат double из метода
Формат
dreturn
Формы
dreturn = 175 (0xaf)
Стек операндов
..., значение →
[пусто]
Описание
Текущий метод должен иметь тип возвращаемого значения double. Значение должно быть типа double. Если текущий метод является synchronized методом, монитор, введённый или повторно введённый при вызове метода, обновляется и, возможно, выходит, как если бы была выполнена инструкция monitorexit (§monitorexit) в текущем потоке. Если исключение не выбрасывается, значение извлекается из стека операндов текущей рамки (§2.6) и подвергается преобразованию типа (§2.8.3), что приводит к значение'. Значение' помещается в стек операндов рамки вызывающего метода. Любые другие значения в стеке операндов текущего метода удаляются.
Затем интерпретатор возвращает управление вызывающему методу, восстанавливая рамку вызывающего метода.
Исключения во время выполнения
Если реализация виртуальной машины Java не применяет правила по структурированному блокированию, описанные в §2.11.10, то если текущий метод является synchronized методом, и текущий поток не является владельцем монитора, введённого или повторно введённого при вызове метода, dreturn выбрасывает IllegalMonitorStateException. Это может произойти, например, если synchronized метод содержит инструкцию monitorexit, но не инструкцию monitorenter, на объекте, на котором синхронизирован метод.
В противном случае, если реализация виртуальной машины Java применяет правила по структурированному блокированию, описанные в §2.11.10, и если первое из этих правил нарушено во время вызова текущего метода, то dreturn выбрасывает IllegalMonitorStateException.
dstore
Операция
Сохранить double в локальную переменную
Формат
dstore
индекс
Формы
dstore = 57 (0x39)
Стек операндов
..., значение →
...
Описание
Индекс — это байт без знака. И индекс, и индекс+1 должны быть индексами в массив локальных переменных текущей области видимости (§2.6). Значение значение вверху стека операндов должно быть типа double. Оно извлекается из стека операндов и преобразуется в соответствии со значением множества (§2.8.3), что приводит к значение'. Локальные переменные по индексам индекс и индекс+1 устанавливаются в значение'.
Примечания
Операцию dstore можно использовать совместно с инструкцией wide (§wide), чтобы получить доступ к локальной переменной с помощью двубайтового индекса без знака.
dstore_
Операция
Сохранить double в локальную переменную
Формат
dstore_
Формы
dstore_0 = 71 (0x47)
dstore_1 = 72 (0x48)
dstore_2 = 73 (0x49)
dstore_3 = 74 (0x4a)
Стек операндов
..., значение →
...
Описание
И <n>, и <n>+1 должны быть индексами в массив локальных переменных текущей области видимости (§2.6). Значение значение вверху стека операндов должно быть типа double. Оно извлекается из стека операндов и преобразуется в соответствии со значением множества (§2.8.3), что приводит к значение'. Локальные переменные по индексам <n> и <n>+1 устанавливаются в значение'.
Примечания
Каждая из инструкций dstore_
dsub
Операция
Вычесть double
Формат
dsub
Формы
dsub = 103 (0x67)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
значение1 и значение2 должны быть типа double. Значения извлекаются из стека операндов и преобразуются в соответствии со значением множества (§2.8.3), что приводит к значение1' и значение2'. Результат результат — это значение1' - значение2'. Результат помещается в стек операндов.
Для double вычитания всегда выполняется, что a-b даёт тот же результат, что и a+(-b). Однако для инструкции dsub вычитание из нуля не равно отрицанию, потому что если x равно +0.0, то 0.0-x равно +0.0, но -x равно -0.0.
Машина Java Virtual требует поддержки постепенного переполнения, как определено в IEEE 754. Несмотря на то, что может произойти переполнение, недополнение или потеря точности, выполнение инструкции dsub никогда не вызывает исключение во время выполнения.
dup
Операция
Дублировать значение верха стека операндов
Формат
dup
Формы
dup = 89 (0x59)
Стек операндов
..., значение →
..., значение, значение
Описание
Дублировать верхнее значение в стеке операндов и поместить дублированное значение в стек операндов.
Инструкцию dup нельзя использовать, если значение не является значением вычислительного типа категории 1 (§2.11.1).
dup_x1
Операция
Дублирует верхнее значение стека операндов и вставляет его на две позиции ниже.
Формат
dup_x1
Формы
dup_x1 = 90 (0x5a)
Стек операндов
..., value2, value1 →
..., value1, value2, value1
Описание
Дублирует верхнее значение в стеке операндов и вставляет дубликат на две позиции ниже в стеке операндов.
Инструкцию dup_x1 следует использовать только в том случае, если как value1, так и value2 являются значениями вычислительного типа категории 1 (§2.11.1).
dup_x2
Операция
Дублирует верхнее значение стека операндов и вставляет его на две или три позиции ниже.
Формат
dup_x2
Формы
dup_x2 = 91 (0x5b)
Стек операндов
Форма 1:
..., value3, value2, value1 →
..., value1, value3, value2, value1
где value1, value2 и value3 — значения вычислительного типа категории 1 (§2.11.1).
Форма 2:
..., value2, value1 →
..., value1, value2, value1
где value1 — значение вычислительного типа категории 1, а value2 — значение вычислительного типа категории 2 (§2.11.1).
Описание
Дублирует верхнее значение стека операндов и вставляет дубликат на две или три позиции ниже в стеке операндов.
dup2
Операция
Дублирует одно или два верхних значения стека операндов.
Формат
dup2
Формы
dup2 = 92 (0x5c)
Стек операндов
Форма 1:
..., value2, value1 →
..., value2, value1, value2, value1
где value1 и value2 — значения вычислительного типа категории 1 (§2.11.1).
Форма 2:
..., value →
..., value, value
где value — значение вычислительного типа категории 2 (§2.11.1).
Описание
Дублирует одно или два верхних значения стека операндов и возвращает дублированные значения в исходном порядке в стек операндов.
dup2_x1
Операция
Дублирует одно или два верхних значения стека операндов и вставляет их на две или три позиции ниже.
Формат
dup2_x1
Формы
dup2_x1 = 93 (0x5d)
Стек операндов
Форма 1:
..., value3, value2, value1 →
..., value2, value1, value3, value2, value1
где value1, value2 и value3 — значения вычислительного типа категории 1 (§2.11.1).
Форма 2:
..., value2, value1 →
..., value1, value2, value1
где value1 — значение вычислительного типа категории 2, а value2 — значение вычислительного типа категории 1 (§2.11.1).
Описание
Дублирует одно или два верхних значения стека операндов и вставляет дублированные значения в исходном порядке на одну позицию ниже исходного значения или значений в стеке операндов.
dup2_x2
Операция
Дублирует верхнее или два верхних значения стека операндов и вставляет их на две, три или четыре позиции вниз.
Формат
dup2_x2
Формы
dup2_x2 = 94 (0x5e)
Стек операндов
Форма 1:
..., value4, value3, value2, value1 →
..., value2, value1, value4, value3, value2, value1
где value1, value2, value3 и value4 — значения вычислительного типа категории 1 (§2.11.1).
Форма 2:
..., value3, value2, value1 →
..., value1, value3, value2, value1
где value1 — значение вычислительного типа категории 2, а value2 и value3 — значения вычислительного типа категории 1 (§2.11.1).
Форма 3:
..., value3, value2, value1 →
..., value2, value1, value3, value2, value1
где value1 и value2 — значения вычислительного типа категории 1, а value3 — значение вычислительного типа категории 2 (§2.11.1).
Форма 4:
..., value2, value1 →
..., value1, value2, value1
где value1 и value2 — значения вычислительного типа категории 2 (§2.11.1).
Описание
Дублирует одно или два верхних значения в стеке операндов и вставляет дублированные значения в исходном порядке в стек операндов.
f2d
Операция
Преобразовать float в double
Формат
f2d
Формы
f2d = 141 (0x8d)
Стек операндов
..., value →
..., result
Описание
Значение value вверху стека операндов должно быть типа float. Оно извлекается из стека операндов и подвергается преобразованию набора значений (§2.8.3), в результате чего получается value'. Затем value' преобразуется в double result. Это result помещается в стек операндов.
Примечания
В случае, когда инструкция f2d является FP-строгой (§2.8.2), она выполняет расширяющее преобразование примитивных типов (JLS §5.1.2). Так как все значения набора значений с плавающей запятой типа float (§2.3.2) точно представимы значениями набора значений с плавающей запятой типа double (§2.3.2), такое преобразование точное.
В случае, если инструкция f2d не является FP-строгой, результат преобразования может быть взят из набора значений с плавающей запятой с расширенным порядком; он не обязательно округляется до ближайшего представимого значения в наборе значений типа double. Однако, если операнд value взят из набора значений с плавающей запятой с расширенным порядком, а целевой результат ограничен набором значений типа double, округление value может потребоваться.
f2i
Операция
Преобразовать float в int
Формат
f2i
Формы
f2i = 139 (0x8b)
Стек операндов
..., value →
..., result
Описание
Значение value на вершине стека операндов должно быть типа float. Оно извлекается из стека операндов и подвергается преобразованию набора значений (§2.8.3), в результате чего получается value'. Затем value' преобразуется в целое значение int result. Это result помещается в стек операндов:
-
Если value' — NaN, то result преобразования — целое 0.
-
В противном случае, если value' не является бесконечностью, оно округляется до целого значения V, используя округление к нулю в соответствии с IEEE 754. Если это целое значение V может быть представлено как
int, то result — этоintзначение V. -
В противном случае, либо 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 неупорядочен, поэтому любое сравнение, в котором один или оба операнда являются NaN, завершается неудачей. Наличие как fcmpg, так и fcmpl позволяет скомпилировать любое сравнение так, чтобы на стек операндов помещалось то же result независимо от того, завершается ли сравнение неудачей на значениях, не являющихся NaN, или по причине NaN. Дополнительную информацию можно найти в §3.5.
fconst_<f>
Операция
Положить float
Формат
fconst_<f>
Формы
fconst_0 = 11 (0xb)
fconst_1 = 12 (0xc)
fconst_2 = 13 (0xd)
Стек операндов
... →
..., <f>
Описание
Поместить константу float <f> (0.0, 1.0 или 2.0) на стек операндов.
fdiv
Операция
Деление float
Формат
fdiv
Формы
fdiv = 110 (0x6e)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа float. Значения извлекаются из стека операндов и подвергаются преобразованию типов (§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)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа float. Значения извлекаются из стека операндов и подвергаются преобразованию набора значений (§2.8.3), что приводит к значение1' и значение2'. float результат равен значение1' * значение2'. Результат помещается в стек операндов.
Результат инструкции fmul определяется правилами арифметики IEEE:
-
Если значение1' или значение2' равно NaN, результат равен NaN.
-
Если ни значение1' ни значение2' не равны NaN, знак результата положительный, если оба значения имеют одинаковый знак, и отрицательный, если значения имеют разные знаки.
-
Умножение бесконечности на ноль приводит к NaN.
-
Умножение бесконечности на конечное значение приводит к бесконечности соответствующего знака, с использованием описанных правил знака.
-
В остальных случаях, когда не участвуют бесконечность или NaN, произведение вычисляется и округляется до ближайшего представимого значения с использованием режима округления IEEE 754 до ближайшего. Если значение слишком велико для представления как
float, мы говорим об переполнении; результат тогда представляет собой бесконечность соответствующего знака. Если значение слишком мало для представления какfloat, мы говорим об подпотоке; результат тогда представляет собой ноль соответствующего знака.
Виртуальная машина Java требует поддержки постепенного подпотока, как определено в IEEE 754. Несмотря на то, что могут произойти переполнение, подпоток или потеря точности, выполнение инструкции fmul никогда не вызывает исключения во время выполнения.
fneg
Операция
Изменение знака float
Формат
fneg
Формы
fneg = 118 (0x76)
Стек операндов
..., значение →
..., результат
Описание
Значение должно быть типа float. Оно извлекается из стека операндов и подвергается преобразованию набора значений (§2.8.3), что приводит к значение'. float результат — арифметическое отрицание значение'. Результат помещается в стек операндов.
Для float значений, отрицание не равно вычитанию из нуля. Если x равно +0.0, то 0.0-x равно +0.0, но -x равно -0.0. Унарный минус просто меняет знак float.
Особые случаи:
-
Если операнд равен NaN, результат равен NaN (напоминаем, что NaN не имеет знака).
-
Если операнд — бесконечность, результат — бесконечность противоположного знака.
-
Если операнд — ноль, результат — ноль противоположного знака.
frem
Операция
Остаток float
Формат
frem
Формы
frem = 114 (0x72)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа float. Значения извлекаются из стека операндов и претерпевают преобразование набора значений (§2.8.3), что приводит к значение1' и значение2'. Результат вычисляется и помещается в стек операндов как float.
Результат инструкции frem отличается от результата так называемой операции вычисления остатка, определенной стандартом IEEE 754. Операция вычисления остатка в IEEE 754 вычисляет остаток от округленного деления, а не от усеченного деления, поэтому ее поведение не аналогично поведению обычного оператора вычисления остатка целых чисел. Вместо этого виртуальная машина Java определяет поведение frem как аналогичное поведению инструкций виртуальной машины Java для вычисления остатка целых чисел (irem и lrem); это можно сравнить с функцией C-библиотеки fmod.
Результат инструкции frem регулируется следующими правилами:
-
Если значение1' или значение2' равно NaN, результат равен NaN.
-
Если ни значение1' ни значение2' не равно NaN, знак результата равен знаку делимого.
-
Если делимое — бесконечность или делитель — ноль или оба, результат равен NaN.
-
Если делимое — конечное число, а делитель — бесконечность, результат равен делимому.
-
Если делимое — ноль, а делитель — конечное число, результат равен делимому.
-
В остальных случаях, когда ни один операнд не является бесконечностью, нулём или NaN, остаток с плавающей точкой результат от делимого значение1' и делителя значение2' определяется математическим соотношением результат = значение1' - (значение2' * q), где q — целое число, которое отрицательно только если значение1' / значение2' отрицательно и положительно только если значение1' / значение2' положительно, и его величина настолько велика, насколько это возможно, не превышая величины истинного математического частного от значение1' и значение2'.
Несмотря на то, что может произойти деление на ноль, вычисление инструкции frem никогда не вызывает исключения во время выполнения. Переполнение, недополнение или потеря точности невозможны.
Примечания
Операцию вычисления остатка IEEE 754 можно вычислить с помощью библиотечной функции Math.IEEEremainder.
freturn
Операция
Возврат float из метода
Формат
freturn
Формы
freturn = 174 (0xae)
Стек операндов
..., значение →
[пустой]
Описание
Текущий метод должен иметь тип возвращаемого значения float. Значение должно быть типа float. Если текущий метод является synchronized методом, монитор, введённый или повторно введённый при вызове метода, обновляется и, возможно, выходит, как если бы выполнялась инструкция monitorexit (§monitorexit) в текущем потоке. Если исключение не выбрасывается, значение извлекается из стека операндов текущей рамки (§2.6) и претерпевает преобразование набора значений (§2.8.3), что приводит к значение'. Значение' помещается в стек операндов рамки вызывающего метода.
Затем интерпретатор возвращает управление вызывающему методу, восстанавливая рамку вызывающего метода.
Исключения во время выполнения
Если реализация виртуальной машины 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_
Операция
Сохранить float в локальную переменную
Формат
fstore_
Формы
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_
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 →
..., value
Описание
Объект objectref, который должен быть типа reference, извлекается из стека операндов. Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения по этому индексу должен быть символической ссылкой на поле (§5.1), которая содержит имя и дескриптор поля, а также символическую ссылку на класс, в котором находится поле. Ссылка на поле разрешается (§5.4.3.2). Значение value указанного поля в objectref извлекается и помещается в стек операндов.
Тип objectref не должен быть типом массива. Если поле является protected, и оно является членом суперкласса текущего класса, и поле не объявлено в том же пакете времени выполнения (§5.3), что и текущий класс, то класс objectref должен быть либо текущим классом, либо подклассом текущего класса.
Исключения связывания
При разрешении символической ссылки на поле может быть выброшено любое из ошибок, относящихся к разрешению поля (§5.4.3.2).
В противном случае, если разрешенное поле является static полем, getfield выбрасывает IncompatibleClassChangeError.
Исключение во время выполнения
В противном случае, если objectref является null, инструкция getfield выбрасывает NullPointerException.
Примечания
Инструкция getfield не может использоваться для доступа к полю length массива. Вместо этого используется инструкция arraylength (§arraylength).
getstatic
Операция
Получение поля static из класса
Формат
getstatic
indexbyte1
indexbyte2
Формы
getstatic = 178 (0xb2)
Стек операндов
..., →
..., value
Описание
Беззнаковые 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
Операция
Безусловный переход (широкий индекс)
Формат
goto_w
branchbyte1
branchbyte2
branchbyte3
branchbyte4
Формы
goto_w = 200 (0xc8)
Стек операндов
Без изменений
Описание
Беззнаковые байты branchbyte1, branchbyte2, branchbyte3 и branchbyte4 используются для построения знакового 32-битного branchoffset, где branchoffset равно (branchbyte1 << 24) | (branchbyte2 << 16) | (branchbyte3 << 8) | branchbyte4. Выполнение продолжается с этого смещения от адреса кода операции этой инструкции goto_w. Целевой адрес должен быть адресом кода операции инструкции в методе, содержащем эту инструкцию goto_w.
Примечания
Несмотря на то, что инструкция goto_w принимает 4-байтовое смещение ветви, другие факторы ограничивают размер метода 65535 байтами (§4.11). Этот предел может быть увеличен в будущих выпусках виртуальной машины Java.
i2b
Операция
Преобразовать int в byte
Формат
i2b
Формы
i2b = 145 (0x91)
Стек операндов
..., value →
..., result
Описание
Значение value в вершине стека операндов должно быть типа int. Оно извлекается из стека операндов, усекается до byte, затем расширяется по знаку до int result. Этот result помещается в стек операндов.
Примечания
Инструкция i2b выполняет сужающее примитивное преобразование (JLS §5.1.3). Она может потерять информацию об общей величине value. result также может не иметь того же знака, что и value.
i2c
Операция
Преобразовать int в char
Формат
i2c
Формы
i2c = 146 (0x92)
Стек операндов
..., value →
..., result
Описание
Значение value в вершине стека операндов должно быть типа int. Оно извлекается из стека операндов, усекается до char, затем расширяется нулем до int result. Этот result помещается в стек операндов.
Примечания
Инструкция i2c выполняет сужающее примитивное преобразование (JLS §5.1.3). Она может потерять информацию об общей величине value. result (который всегда положителен) также может не иметь того же знака, что и value.
i2d
Операция
Преобразовать int в double
Формат
i2d
Формы
i2d = 135 (0x87)
Стек операндов
..., value →
..., result
Описание
Значение value в вершине стека операндов должно быть типа int. Оно извлекается из стека операндов и преобразуется в double result. result помещается в стек операндов.
Примечания
Инструкция i2d выполняет расширяющее примитивное преобразование (JLS §5.1.2). Поскольку все значения типа int точно представимы типом double, преобразование является точным.
i2f
Операция
Преобразовать int в float
Формат
i2f
Формы
i2f = 134 (0x86)
Стек операндов
..., значение →
..., результат
Описание
Значение значение на вершине стека операндов должно быть типа 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)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа int. Они извлекаются из стека операндов. Вычисляется int результат путём поразрядного И (конъюнкции) значение1 и значение2. Результат помещается в стек операндов.
iastore
Операция
Запись в int массив
Формат
iastore
Формы
iastore = 79 (0x4f)
Стек операндов
..., ссылка_на_массив, индекс, значение →
...
Описание
Ссылка_на_массив должна быть типа reference и ссылаться на массив, компоненты которого имеют тип int. Индекс и значение должны быть типа int. Ссылка_на_массив, индекс и значение извлекаются из стека операндов. Значение записывается в качестве компонента массива с индексом индекс.
Исключения во время выполнения
Если ссылка_на_массив является null, iastore генерирует исключение NullPointerException.
В противном случае, если индекс выходит за пределы массива, к которому ссылается ссылка_на_массив, инструкция 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)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа int. Значения извлекаются из стека операндов. int результат – значение выражения языка программирования Java значение1 / значение2. Результат помещается в стек операндов.
Деление 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. Затем выполнение продолжается по смещению от адреса кода данной инструкции if_acmp<cond>. Целевой адрес должен быть адресом кода инструкции в методе, содержащем эту инструкцию if_acmp<cond>.
В противном случае, если сравнение не выполняется, выполнение продолжается по адресу инструкции, следующей за этой инструкцией if_acmp<cond>.
if_icmp<cond>
Операция
Переход, если int сравнение успешно
Формат
if_icmp<cond>
branchbyte1
branchbyte2
Формы
if_icmpeq = 159 (0x9f)
if_icmpne = 160 (0xa0)
if_icmplt = 161 (0xa1)
if_icmpge = 162 (0xa2)
if_icmpgt = 163 (0xa3)
if_icmple = 164 (0xa4)
Стек операндов
..., value1, value2 →
...
Описание
И value1, и value2 должны быть типа int. Оба они извлекаются из стека операндов и сравниваются. Все сравнения выполняются со знаком. Результаты сравнения следующие:
-
if_icmpeq успешно выполняется тогда и только тогда, когда value1 = value2
-
if_icmpne успешно выполняется тогда и только тогда, когда value1 ≠ value2
-
if_icmplt успешно выполняется тогда и только тогда, когда value1 < value2
-
if_icmple успешно выполняется тогда и только тогда, когда value1 ≤ value2
-
if_icmpgt успешно выполняется тогда и только тогда, когда value1 > value2
-
if_icmpge успешно выполняется тогда и только тогда, когда value1 ≥ value2
Если сравнение успешно, незначащие branchbyte1 и branchbyte2 используются для построения знаковой 16-разрядной смещения, где смещение вычисляется как (branchbyte1 << 8) | branchbyte2. Затем выполнение продолжается по смещению от адреса кода данной инструкции if_icmp<cond>. Целевой адрес должен быть адресом кода инструкции в методе, содержащем эту инструкцию if_icmp<cond>.
В противном случае, выполнение продолжается по адресу инструкции, следующей за этой инструкцией if_icmp<cond>.
if<cond>
Операция
Ветвь, если int сравнение с нулём успешно
Формат
if<cond>
branchbyte1
branchbyte2
Формы
ifeq = 153 (0x99)
ifne = 154 (0x9a)
iflt = 155 (0x9b)
ifge = 156 (0x9c)
ifgt = 157 (0x9d)
ifle = 158 (0x9e)
Стек операндов
..., value →
...
Описание
Значение value должно быть типа int. Оно извлекается из стека операндов и сравнивается с нулём. Все сравнения выполняются со знаком. Результаты сравнений следующие:
-
ifeq успешно, если и только если value = 0
-
ifne успешно, если и только если value ≠ 0
-
iflt успешно, если и только если value < 0
-
ifle успешно, если и только если value ≤ 0
-
ifgt успешно, если и только если value > 0
-
ifge успешно, если и только если value ≥ 0
Если сравнение успешно, незначащие branchbyte1 и branchbyte2 используются для построения 16-разрядного смещения со знаком, где смещение рассчитывается как (branchbyte1 << 8) | branchbyte2. Затем выполнение продолжается в позиции, смещённой на это значение относительно адреса инструкции if<cond>. Целевой адрес должен быть адресом инструкции внутри метода, содержащего эту инструкцию if<cond>.
В противном случае выполнение продолжается по адресу инструкции, следующей за инструкцией if<cond>.
ifnonnull
Операция
Ветвь, если reference не null
Формат
ifnonnull
branchbyte1
branchbyte2
Формы
ifnonnull = 199 (0xc7)
Стек операндов
..., value →
...
Описание
Значение value должно быть типа reference. Оно извлекается из стека операндов. Если value не null, незначащие branchbyte1 и branchbyte2 используются для построения 16-разрядного смещения со знаком, где смещение рассчитывается как (branchbyte1 << 8) | branchbyte2. Затем выполнение продолжается в позиции, смещённой на это значение относительно адреса инструкции ifnonnull. Целевой адрес должен быть адресом инструкции внутри метода, содержащего эту инструкцию ifnonnull.
В противном случае выполнение продолжается по адресу инструкции, следующей за инструкцией ifnonnull.
ifnull
Операция
Ветвь, если reference является null
Формат
ifnull
branchbyte1
branchbyte2
Формы
ifnull = 198 (0xc6)
Стек операндов
..., value →
...
Описание
Значение value должно быть типа reference. Оно извлекается из стека операндов. Если value является null, незначащие branchbyte1 и branchbyte2 используются для построения 16-разрядного смещения со знаком, где смещение рассчитывается как (branchbyte1 << 8) | branchbyte2. Затем выполнение продолжается в позиции, смещённой на это значение относительно адреса инструкции ifnull. Целевой адрес должен быть адресом инструкции внутри метода, содержащего эту инструкцию ifnull.
В противном случае выполнение продолжается по адресу инструкции, следующей за инструкцией ifnull.
iinc
Операция
Увеличить локальную переменную на константу
Формат
iinc
index
const
Формы
iinc = 132 (0x84)
Стек операндов
Без изменений
Описание
index — это беззнаковый байт, который должен быть индексом в массив локальных переменных текущей рамки (§2.6). const — это непосредственный байт со знаком. Локальная переменная по индексу index должна содержать int. Сначала значение const расширяется со знаком до int, а затем локальная переменная по индексу index увеличивается на это значение.
Примечания
Инструкция iinc может использоваться совместно с инструкцией wide (§wide) для доступа к локальной переменной с помощью двухбайтового беззнакового индекса и для увеличения её на двухбайтовое значение со знаком.
iload
Операция
Загрузка int из локальной переменной
Формат
iload
индекс
Формы
iload = 21 (0x15)
Стек операндов
... →
..., значение
Описание
Индекс — это беззнаковый байт, который должен быть индексом в массив локальных переменных текущей рамки (§2.6). Локальная переменная по индексу должна содержать int. Значение локальной переменной по индексу помещается в стек операндов.
Примечания
Код iload можно использовать совместно с инструкцией wide (§wide), чтобы получить доступ к локальной переменной с помощью двубайтного беззнакового индекса.
iload_
Операция
Загрузка int из локальной переменной
Формат
iload_
Формы
iload_0 = 26 (0x1a)
iload_1 = 27 (0x1b)
iload_2 = 28 (0x1c)
iload_3 = 29 (0x1d)
Стек операндов
... →
..., значение
Описание
<n> — должно быть индексом в массив локальных переменных текущей рамки (§2.6). Локальная переменная по <n> должна содержать int. Значение локальной переменной по <n> помещается в стек операндов.
Примечания
Каждая из инструкций iload_
imul
Операция
Умножение int
Формат
imul
Формы
imul = 104 (0x68)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
И значение1, и значение2 должны быть типа int. Значения извлекаются из стека операндов. Результат результат равен значение1 * значение2. Результат помещается в стек операндов.
Результат — это 32 младших бита истинного математического результата в достаточном широком формате дополнения до двух, представленного как значение типа int. При переполнении знак результата может не совпадать со знаком математического произведения двух значений.
Несмотря на то, что может произойти переполнение, выполнение инструкции imul никогда не вызывает исключение во время выполнения.
ineg
Операция
Отрицание int
Формат
ineg
Формы
ineg = 116 (0x74)
Стек операндов
..., значение →
..., результат
Описание
Значение должно быть типа int. Оно извлекается из стека операндов. Результат результат — арифметическое отрицание значения, -значение. Результат помещается в стек операндов.
Для значений int, отрицание равно вычитанию из нуля. Поскольку Java Virtual Machine использует представление целых чисел в формате дополнения до двух, и диапазон значений дополнения до двух несимметричен, отрицание максимального отрицательного int приводит к тому же максимальному отрицательному числу. Несмотря на то, что произошло переполнение, исключение не генерируется.
Для всех значений int x, -x равно (~x)+1.
instanceof
Операция
Определить, является ли объект заданного типа
Формат
instanceof
indexbyte1
indexbyte2
Формы
instanceof = 193 (0xc1)
Стек операндов
..., objectref →
..., result
Описание
objectref, который должен быть типа reference, извлекается из стека операндов. Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пул констант времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула констант времени выполнения по этому индексу должен быть символической ссылкой на класс, массив или тип интерфейса.
Если objectref является null, инструкция instanceof помещает int значение result равное 0 в качестве int на стек операндов.
В противном случае, указанный класс, массив или тип интерфейса разрешаются (§5.4.3.1). Если objectref является экземпляром разрешенного класса или массива или реализует разрешенный интерфейс, инструкция instanceof помещает int значение result равное 1 в качестве int на стек операндов; в противном случае, она помещает int значение result равное 0.
Следующие правила используются для определения того, является ли objectref, который не является null, экземпляром разрешенного типа: Если S — класс объекта, на который ссылается objectref, а T — разрешенный класс, массив или тип интерфейса, instanceof определяет, является ли objectref экземпляром T следующим образом:
-
Если S — обычный (немассивно-ориентированный) класс, то:
-
Если T — тип класса, то S должен быть тем же классом, что и T, или S должен быть подклассом T;
-
Если T — тип интерфейса, то S должен реализовывать интерфейс T.
-
-
Если S — тип интерфейса, то:
-
Если T — тип класса, то T должен быть
Object. -
Если T — тип интерфейса, то T должен быть тем же интерфейсом, что и S, или суперинтерфейсом S.
-
-
Если S — класс, представляющий тип массива SC
[], то есть массив компонентов типа SC, то:-
Если T — тип класса, то T должен быть
Object. -
Если T — тип интерфейса, то T должен быть одним из интерфейсов, реализуемых массивами (JLS §4.10.3).
-
Если T — тип массива TC
[], то есть массив компонентов типа TC, то одно из следующих утверждений должно быть истинным:-
TC и SC — один и тот же примитивный тип.
-
TC и SC — типы ссылок, и тип SC может быть приведён к TC по этим правилам времени выполнения.
-
-
Исключения связывания
При разрешении символической ссылки на класс, массив или тип интерфейса могут быть выброшены любые исключения, описанные в §5.4.3.1.
Примечания
Инструкция instanceof очень похожа на инструкцию checkcast (§checkcast). Они различаются по обработке null, по поведению при неудачном тесте (checkcast выбрасывает исключение, instanceof возвращает код результата) и по влиянию на стек операндов.
invokedynamic
Операция
Вызов динамического метода
Формат
invokedynamic
indexbyte1
indexbyte2
0
0
Формы
invokedynamic = 186 (0xba)
Стек операндов
..., [arg1, [arg2 ...]] →
...
Описание
Каждое конкретное лексическое вхождение инструкции invokedynamic называется динамической точкой вызова.
Сначала беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения в этом индексе должен быть символической ссылкой на спецификатор точки вызова (§5.1). Значения третьего и четвёртого байтов операндов всегда должны быть равны нулю.
Спецификатор точки вызова разрешается (§5.4.3.6) для этой конкретной динамической точки вызова, чтобы получить reference для метода-загрузчика, reference для экземпляра java.lang.invoke.MethodType и reference для статических аргументов.
Далее, как часть продолжения разрешения спецификатора точки вызова, метод-загрузчик вызывается так, как если бы выполнялась инструкция invokevirtual (§invokevirtual), которая содержит индекс пула постоянных времени выполнения к символической ссылке R, где:
-
R является символической ссылкой на метод класса (§5.1);
-
для символической ссылки на класс, в котором должен быть найден метод, R указывает
java.lang.invoke.MethodHandle; -
для имени метода, R указывает
invoke; -
для дескриптора метода, R указывает тип возвращаемого значения
java.lang.invoke.CallSiteи типы параметров, полученные из элементов, помещенных в стек операндов.Первые три типа параметров —
java.lang.invoke.MethodHandles.Lookup,Stringиjava.lang.invoke.MethodTypeв указанном порядке. Если спецификатор точки вызова содержит статические аргументы, то для каждого аргумента добавляется тип параметра к типам параметров дескриптора метода в порядке, в котором аргументы были помещены в стек операндов. Эти типы параметров могут бытьClass,java.lang.invoke.MethodHandle,java.lang.invoke.MethodType,String,int,long,floatилиdouble.
и где, как будто на стек операндов последовательно помещались следующие элементы:
-
referenceкjava.lang.invoke.MethodHandleобъекту для метода-загрузчика; -
referenceкjava.lang.invoke.MethodHandles.Lookupобъекту класса, в котором происходит эта динамическая точка вызова; -
referenceкStringдля имени метода в спецификаторе точки вызова; -
referenceкjava.lang.invoke.MethodTypeобъекту, полученному для дескриптора метода в спецификаторе точки вызова; -
referenceк классам, типам методов, обработчикам методов и строковым литералам, обозначенным как статические аргументы в спецификаторе точки вызова, и числовым значениям (§2.3.1, §2.3.2), обозначенным как статические аргументы в спецификаторе точки вызова, в порядке их появления в спецификаторе точки вызова. (То есть для примитивных значений не происходит упаковка.)
Символическая ссылка R описывает полиморфный по сигнатуре метод (§2.9). Из-за работы invokevirtual над полиморфным по сигнатуре методом, называемым invoke, тип дескриптора получающего обработчика метода (представляющего метод-загрузчик) не обязательно должен быть семантически равен дескриптору метода, указанному в R. Например, первый тип параметра, указанный в R, мог бы быть Object вместо java.lang.invoke.MethodHandles.Lookup, а тип возвращаемого значения, указанный в R, мог бы быть Object вместо java.lang.invoke.CallSite. До тех пор, пока метод-загрузчик может быть вызван методом invoke без генерации java.lang.invoke.WrongMethodTypeException, тип дескриптора обработчика метода, который представляет метод-загрузчик, произволен.
Если метод-загрузчик является методом с переменным числом аргументов, то некоторые или все аргументы в стеке операндов, указанные выше, могут быть собраны в массив параметров.
Вызов метода-загрузчика происходит в потоке, который пытается разрешить символическую ссылку на спецификатор точки вызова этой динамической точки вызова. Если таких потоков несколько, метод-загрузчик может быть вызван в нескольких потоках одновременно. Поэтому методы-загрузчики, которые обращаются к глобальным данным приложения, должны принимать обычные меры предосторожности против гонок.
Результат, возвращённый методом-загрузчиком, должен быть reference к объекту, чьим классом является java.lang.invoke.CallSite или подклассом java.lang.invoke.CallSite. Этот объект известен как объект точки вызова. reference извлекается из стека операндов, как будто при выполнении инструкции invokevirtual.
Если несколько потоков одновременно выполняют метод-загрузчик для одной и той же динамической точки вызова, Java Virtual Machine должна выбрать один возвращённый объект точки вызова и установить его для всех потоков. Любые другие методы-загрузчики, выполняющиеся для динамической точки вызова, разрешены до завершения, но их результаты игнорируются, и выполнение динамической точки вызова в потоках продолжается с выбранным объектом точки вызова.
Объект точки вызова имеет тип дескриптора (экземпляр java.lang.invoke.MethodType), который должен быть семантически равен java.lang.invoke.MethodType, полученному для дескриптора метода в спецификаторе точки вызова.
Результатом успешного разрешения спецификатора точки вызова является объект точки вызова, который навсегда привязан к динамической точке вызова.
Вызывается обработчик метода, представленный целью объекта привязанной точки вызова. Вызов происходит как при выполнении инструкции invokevirtual (§invokevirtual), которая указывает индекс пула постоянных времени выполнения на символическую ссылку на метод (§5.1) со следующими свойствами:
-
Имя метода —
invokeExact; -
Дескриптор метода — дескриптор метода в спецификаторе точки вызова; и
-
Символическая ссылка метода на класс, в котором должен быть найден метод, указывает на класс
java.lang.invoke.MethodHandle.
Стек операндов будет интерпретироваться как содержащий reference к цели объекта точки вызова, за которым следуют nargs аргументов, где число, тип и порядок значений должны соответствовать дескриптору метода в спецификаторе точки вызова.
Исключения связывания
Если разрешение символической ссылки на спецификатор места вызова вызывает исключение E, инструкция invokedynamic генерирует BootstrapMethodError, который оборачивает E.
В противном случае, во время продолжения разрешения спецификатора места вызова, если вызов метода-загрузчика завершается неожиданно (§2.6.5) из-за генерации исключения E, инструкция invokedynamic генерирует BootstrapMethodError, который оборачивает E. (Это может произойти, если метод-загрузчик имеет неправильную арность, тип параметра или тип возвращаемого значения, что приводит к java.lang.invoke.MethodHandle . invoke генерировать java.lang.invoke.WrongMethodTypeException.)
В противном случае, во время продолжения разрешения спецификатора места вызова, если результат вызова метода-загрузчика не является reference экземпляра java.lang.invoke.CallSite, инструкция invokedynamic генерирует BootstrapMethodError.
В противном случае, во время продолжения разрешения спецификатора места вызова, если описатель типа целевого объекта места вызова не семантически равен описателю метода в спецификаторе места вызова, инструкция invokedynamic генерирует BootstrapMethodError.
Исключения во время выполнения
Если данное динамическое место вызова завершило разрешение своего спецификатора места вызова, это подразумевает, что ссылка на экземпляр java.lang.invoke.CallSite связана с этим динамическим местом вызова. Следовательно, элемент стека операндов, представляющий ссылку на целевой объект места вызова, никогда не null. Аналогично, это подразумевает, что описатель метода в спецификаторе места вызова семантически равен описателю типа обрабатываемого метода-обработчика, как будто выполняется инструкция invokevirtual. Вместе эти инварианты означают, что инструкция invokedynamic, связанная с объектом места вызова, никогда не генерирует NullPointerException или java.lang.invoke.WrongMethodTypeException.
invokeinterface
Операция
Вызов метода интерфейса
Формат
invokeinterface
indexbyte1
indexbyte2
count
0
Формы
invokeinterface = 185 (0xb9)
Стек операндов
..., objectref, [arg1, [arg2 ...]] →
...
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в пуле постоянных времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент пула постоянных времени выполнения в этом индексе должен быть символической ссылкой на метод интерфейса (§5.1), который задаёт имя и дескриптор (§4.3.3) метода интерфейса, а также символическую ссылку на интерфейс, в котором находится метод интерфейса. Иметованный метод интерфейса разрешается (§5.4.3.4).
Разрешённый метод интерфейса не должен быть методом инициализации экземпляра или методом инициализации класса или интерфейса (§2.9).
Операнд count — беззнаковый байт, который не должен быть нулём. objectref должен быть типа reference и должен следовать за ним в стеке операндов nargs значениями аргументов, где количество, тип и порядок значений должны соответствовать дескриптору разрешённого метода интерфейса. Значение четвёртого байта операнда всегда должно быть нулём.
Пусть C — класс objectref. Фактический вызываемый метод выбирается с помощью следующей процедуры поиска:
-
Если C содержит объявление метода экземпляра с тем же именем и дескриптором, что и разрешённый метод, то это и есть вызываемый метод.
-
В противном случае, если у C есть суперкласс, производится поиск объявления метода экземпляра с тем же именем и дескриптором, что и разрешённый метод, начиная с непосредственного суперкласса C и продолжая с непосредственного суперкласса этого класса и так далее, пока не будет найдено совпадение или не останется больше суперклассов. Если совпадение найдено, то это и есть вызываемый метод.
-
В противном случае, если в суперинтерфейсах C существует ровно один максимально-специфичный метод (§5.4.3.3), который соответствует имени и дескриптору разрешённого метода и не является
abstract, то это и есть вызываемый метод.
Если метод является synchronized, монитор, связанный с objectref, входит или повторно входит, как если бы был выполнен оператор monitorenter (§monitorenter) в текущем потоке.
Если метод не является native, nargs значения аргументов и objectref извлекаются из стека операндов. Для вызываемого метода создаётся новый фрейм в стеке виртуальной машины Java. objectref и значения аргументов последовательно становятся значениями локальных переменных нового фрейма, при этом objectref в локальной переменной 0, arg1 в локальной переменной 1 (или, если arg1 типа long или double, в локальных переменных 1 и 2) и так далее. Любое значение аргумента, имеющее тип с плавающей точкой, подвергается преобразованию набора значений (§2.8.3) перед сохранением в локальной переменной. Новый фрейм затем становится текущим, и виртуальная машина Java устанавливает pc на код первого оператора вызываемого метода. Выполнение продолжается с первого оператора метода.
Если метод является native и зависимый от платформы код, который его реализует, ещё не привязан (§5.6) к виртуальной машине Java, это выполняется. Значения nargs аргументов и objectref извлекаются из стека операндов и передаются как параметры коду, реализующему метод. Любое значение аргумента, имеющее тип с плавающей точкой, подвергается преобразованию набора значений (§2.8.3) перед передачей в качестве параметра. Параметры передаются, и код вызывается способом, зависящим от реализации. При возврате кода зависимого от платформы:
-
Если метод
nativeявляетсяsynchronized, монитор, связанный с objectref, обновляется и, возможно, выходит, как если бы был выполнен оператор monitorexit (§monitorexit) в текущем потоке. -
Если метод
nativeвозвращает значение, возвращаемое значение кода зависимого от платформы преобразуется способом, зависящим от реализации, в тип возврата методаnativeи помещается в стек операндов.
Исключения привязки
При разрешении символической ссылки на метод интерфейса могут быть выброшены любые исключения, относящиеся к разрешению метода интерфейса (§5.4.3.4).
В противном случае, если разрешённый метод является static или private, инструкция invokeinterface выбросит исключение IncompatibleClassChangeError.
Исключения времени выполнения
В противном случае, если objectref является null, инструкция invokeinterface выбросит исключение NullPointerException.
В противном случае, если класс objectref не реализует разрешённый интерфейс, invokeinterface выбросит исключение IncompatibleClassChangeError.
В противном случае, если шаг 1 или шаг 2 процедуры поиска выбирает метод, который не является public, invokeinterface выбросит исключение IllegalAccessError.
В противном случае, если шаг 1 или шаг 2 процедуры поиска выбирает метод abstract, invokeinterface выбросит исключение AbstractMethodError.
В противном случае, если шаг 1 или шаг 2 процедуры поиска выбирает метод native и код, реализующий метод, не может быть привязан, invokeinterface выбросит исключение UnsatisfiedLinkError.
В противном случае, если шаг 3 процедуры поиска определяет, что существует несколько максимально-специфичных методов в суперинтерфейсах C, которые соответствуют имени и дескриптору разрешённого метода и не являются abstract, invokeinterface выбросит исключение IncompatibleClassChangeError.
В противном случае, если шаг 3 процедуры поиска определяет, что существует ноль максимально-специфичных методов в суперинтерфейсах 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).
Если разрешённый метод является protected, и он является членом суперкласса текущего класса, и метод не объявлен в той же среде выполнения пакета (§5.3), что и текущий класс, то класс objectref должен быть либо текущим классом, либо подклассом текущего класса.
Если все перечисленные ниже условия выполняются, пусть 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.
В противном случае, если разрешённый метод является методом protected суперкласса текущего класса, объявленного в другом пакете выполнения, и класс objectref не является текущим классом или подклассом текущего класса, то invokespecial генерирует исключение IllegalAccessError.
В противном случае, если шаг 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), а также private методов и методов суперкласса текущего класса.
Инструкция invokespecial ранее называлась invokenonvirtual до релиза JDK 1.0.2.
Значения аргумента nargs и objectref не однозначны с первыми nargs+1 локальными переменными. Значения аргументов типов long и double должны храниться в двух соседних локальных переменных, поэтому для передачи nargs значений аргументов вызываемому методу может потребоваться больше, чем nargs локальных переменных.
Инструкция invokespecial обрабатывает вызов метода интерфейса private, метода интерфейса, не являющегося abstract, который ссылается на прямой суперинтерфейс, и метода интерфейса, не являющегося 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).
Разрешенный метод не должен быть методом инициализации экземпляра или методом инициализации класса или интерфейса (§2.9).
Разрешенный метод должен быть static, и поэтому не может быть abstract.
При успешном разрешении метода класс или интерфейс, объявивший разрешенный метод, инициализируются (§5.5), если этот класс или интерфейс еще не был инициализирован.
Стек операндов должен содержать nargs значений аргументов, при этом количество, тип и порядок значений должны соответствовать дескриптору разрешенного метода.
Если метод является synchronized, монитор, связанный с объектом Class, входящим в разрешение, вводится или повторно вводится так, как если бы выполняется инструкция monitorenter (§monitorenter) в текущем потоке.
Если метод не native, nargs значений аргументов извлекаются из стека операндов. Для вызываемого метода создаётся новый фрейм в стеке виртуальной машины Java. Значения nargs аргументов последовательно становятся значениями локальных переменных нового фрейма, где arg1 находится в локальной переменной 0 (или, если arg1 имеет тип long или double, в локальных переменных 0 и 1) и так далее. Любое значение аргумента, являющееся типом с плавающей точкой, проходит преобразование набора значений (§2.8.3) перед сохранением в локальную переменную. Новый фрейм затем становится текущим, и виртуальная машина Java устанавливает код операции на код первой инструкции вызываемого метода. Выполнение продолжается с первой инструкции метода.
Если метод является 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).
Если разрешённый метод protected, и он является членом суперкласса текущего класса, и метод не объявлен в той же среде выполнения пакета (§5.3), что и текущий класс, то класс objectref должен быть либо текущим классом, либо подклассом текущего класса.
Если разрешённый метод не является полиморфным по сигнатуре (§2.9), то инструкция invokevirtual выполняется следующим образом.
Пусть C — класс objectref. Фактический вызываемый метод выбирается с помощью следующей процедуры поиска:
-
Если C содержит объявление для метода экземпляра
m, который переопределяет (§5.4.5) разрешённый метод, тоmявляется вызываемым методом. -
В противном случае, если у C есть суперкласс, выполняется поиск объявления метода экземпляра, который переопределяет разрешённый метод, начиная с непосредственного суперкласса C и продолжая с непосредственного суперкласса этого класса и так далее, пока не будет найден переопределяющий метод или не останется больше суперклассов. Если переопределяющий метод найден, он является вызываемым методом.
-
В противном случае, если ровно один максимально специфичный метод (§5.4.3.3) в суперинтерфейсах C соответствует имени и дескриптору разрешённого метода и не является
abstract, то он является вызываемым методом.
За objectref на стеке операндов должны следовать nargs аргументов, где количество, тип и порядок значений должны соответствовать дескриптору выбранного метода экземпляра.
Если метод является synchronized, то монитор, связанный с objectref, вводится или повторно вводится, как если бы выполнялась инструкция monitorenter (§monitorenter) в текущем потоке.
Если метод не является native, то nargs значений аргументов и objectref извлекаются со стека операндов. Для вызываемого метода создаётся новый фрейм на стеке виртуальной машины Java. objectref и значения аргументов последовательно становятся значениями локальных переменных нового фрейма, где objectref находится в локальной переменной 0, arg1 — в локальной переменной 1 (или, если arg1 имеет тип long или double, в локальных переменных 1 и 2) и так далее. Любое значение аргумента с плавающей точкой подвергается преобразованию множества значений (§2.8.3) перед сохранением в локальную переменную. Затем новый фрейм становится текущим, и виртуальная машина Java pc устанавливается на код первой инструкции вызываемого метода. Выполнение продолжается с первой инструкции метода.
Если метод является native, и зависимая от платформы реализация ещё не связана (§5.6) с виртуальной машиной Java, это делается. Значения аргументов nargs и objectref извлекаются со стека операндов и передаются в качестве параметров коду, реализующему метод. Любое значение аргумента с плавающей точкой подвергается преобразованию множества значений (§2.8.3) перед передачей в качестве параметра. Параметры передаются, и код вызывается в зависимости от реализации. Когда код зависимый от платформы возвращается, происходят следующие действия:
-
Если метод
nativeявляетсяsynchronized, монитор, связанный с objectref, обновляется и, возможно, завершается, как если бы выполнялась инструкция monitorexit (§monitorexit) в текущем потоке. -
Если метод
nativeвозвращает значение, возвращаемое значение кода, зависимого от платформы, преобразуется в зависимости от реализации к возвращаемому типу методаnativeи помещается в стек операндов.
Если разрешённый метод является полиморфным по сигнатуре (§2.9), то инструкция invokevirtual выполняется следующим образом.
Сначала получается reference экземпляра java.lang.invoke.MethodType, как если бы разрешалась символическая ссылка на тип метода (§5.4.3.5) с теми же параметрами и возвращаемыми типами, что и дескриптор метода, на который ссылается инструкция invokevirtual.
-
Если названный метод является
invokeExact, экземплярjava.lang.invoke.MethodTypeдолжен быть семантически равен типу дескриптора принимающего обработчика метода objectref. Обработчик метода, который будет вызван — это objectref. -
Если названный метод является
invoke, и экземплярjava.lang.invoke.MethodTypeсемантически равен типу дескриптора принимающего обработчика метода objectref, то обработчик метода, который будет вызван — это objectref. -
Если названный метод является
invoke, и экземплярjava.lang.invoke.MethodTypeне семантически равен типу дескриптора принимающего обработчика метода objectref, то виртуальная машина Java пытается скорректировать тип дескриптора принимающего обработчика метода, как если бы это был вызовjava.lang.invoke.MethodHandle.asType, чтобы получить точно вызываемый обработчик методаm. Обработчик метода, который будет вызван — этоm.
За objectref на стеке операндов должны следовать nargs аргументов, где количество, тип и порядок значений должны соответствовать типу дескриптора вызываемого обработчика метода. (Этот тип дескриптора будет соответствовать дескриптору метода, подходящему для типа обработчика метода, который будет вызван, как указано в §5.4.3.5.)
Затем, если вызываемый обработчик метода имеет байт-код поведение, виртуальная машина Java вызывает обработчик метода как если бы выполнялось байт-код поведение, связанное с типом обработчика метода. Если тип 5 (REF_invokeVirtual), 6 (REF_invokeStatic), 7 (REF_invokeSpecial), 8 (REF_newInvokeSpecial) или 9 (REF_invokeInterface), тогда фрейм будет создан и сделан текущим в процессе выполнения байт-кода; когда вызванный методом байт-код завершается (обычно или неожиданно), фрейм его вызывателя считается фреймом для метода, содержащего эту инструкцию invokevirtual.
Фрейм, в котором выполняется сам байт-код, не виден.
В противном случае, если у вызываемого обработчика метода нет поведения байт-кода, виртуальная машина Java вызывает его в зависимости от реализации.
Исключения при связывании
При разрешении символической ссылки на метод могут быть выброшены любые исключения, относящиеся к разрешению методов (§5.4.3.3).
В противном случае, если разрешенный метод является методом класса (static), инструкция invokevirtual выбросит исключение IncompatibleClassChangeError.
В противном случае, если разрешенный метод является полиморфным по сигнатуре, при разрешении типа метода, полученного из описателя в символической ссылке на метод, могут быть выброшены любые исключения, относящиеся к разрешению типа метода (§5.4.3.5).
Исключения во время выполнения
В противном случае, если objectref является null, инструкция invokevirtual выбросит исключение NullPointerException.
В противном случае, если разрешенный метод является методом protected суперкласса текущего класса, объявленного в другом пакете времени выполнения, и класс objectref не является текущим классом или подклассом текущего класса, то invokevirtual выбросит исключение IllegalAccessError.
В противном случае, если разрешенный метод не является полиморфным по сигнатуре:
-
Если шаг 1 или шаг 2 процедуры поиска выбирают метод
abstract, invokevirtual выбросит исключениеAbstractMethodError. -
В противном случае, если шаг 1 или шаг 2 процедуры поиска выбирают метод
native, и код, реализующий метод, не может быть привязан, invokevirtual выбросит исключениеUnsatisfiedLinkError. -
В противном случае, если шаг 3 процедуры поиска определяет, что существует несколько максимально-специфичных методов в суперинтерфейсах C, которые соответствуют имени и описателю разрешенного метода и не являются
abstract, invokevirtual выбросит исключениеIncompatibleClassChangeError -
В противном случае, если шаг 3 процедуры поиска определяет, что существует ноль максимально-специфичных методов в суперинтерфейсах C, которые соответствуют имени и описателю разрешенного метода и не являются
abstract, invokevirtual выбросит исключениеAbstractMethodError.
В противном случае, если разрешенный метод является полиморфным по сигнатуре:
-
Если имя метода является
invokeExact, и полученный экземплярjava.lang.invoke.MethodTypeне равен по смыслу описателю типа метода, принимающего обработчик, инструкция invokevirtual выбросит исключениеjava.lang.invoke.WrongMethodTypeException. -
Если имя метода является
invoke, и полученный экземплярjava.lang.invoke.MethodTypeне является допустимым аргументом для методаjava.lang.invoke.MethodHandle.asType, вызываемого на принимающем обработчике, инструкция invokevirtual выбросит исключениеjava.lang.invoke.WrongMethodTypeException.
Примечания
Значения аргументов nargs и objectref не находятся в однозначном соответствии с первыми nargs+1 локальными переменными. Значения аргументов типов long и double должны храниться в двух последовательных локальных переменных, поэтому для передачи nargs значений аргументов вызываемому методу может потребоваться больше, чем nargs локальных переменных.
Возможно, что символическая ссылка инструкции invokevirtual разрешается на метод интерфейса. В этом случае возможно, что в иерархии классов нет переопределяющего метода, но соответствующий разрешенному методу метод интерфейса без abstract соответствует описателю разрешенного метода. Логика выбора соответствует такому методу, используя те же правила, что и для invokeinterface.
ior
Операция
Логическое ИЛИ int
Формат
ior
Формы
ior = 128 (0x80)
Стек операндов
..., value1, value2 →
..., result
Описание
И value1, и value2 должны быть типа int. Они извлекаются из стека операндов. Вычисляется результат result путём побитового включительно ИЛИ value1 и value2. Результат result помещается в стек операндов.
irem
Операция
Остаток от деления int
Формат
irem
Формы
irem = 112 (0x70)
Стек операндов
..., value1, value2 →
..., result
Описание
И value1, и value2 должны быть типа int. Значения извлекаются из стека операндов. Результат result — это остаток от деления value1 на value2. Результат помещается в стек операндов.
Результат инструкции irem таков, что (a/b)*b
+ (a%b) равно a. Это тождество выполняется даже в том частном случае, когда делимое является отрицательным int наибольшего возможного значения для его типа, а делитель — -1 (остаток — 0). Из этого правила следует, что результат операции остатка может быть отрицательным только если делимое отрицательное, и может быть положительным только если делимое положительное. Кроме того, абсолютная величина результата всегда меньше абсолютной величины делителя.
Исключение во время выполнения
Если значение делителя для оператора остатка int равно 0, irem выбросит исключение ArithmeticException.
ireturn
Операция
Возврат значения int из метода
Формат
ireturn
Формы
ireturn = 172 (0xac)
Стек операндов
..., значение →
[пустой]
Описание
Текущий метод должен иметь тип возвращаемого значения boolean, byte, short, char или int. Значение значение должно быть типа int. Если текущий метод является методом synchronized, то монитор, вошедший или повторно вошедший во время вызова метода, обновляется и, возможно, выходит, как если бы выполнялась инструкция monitorexit (§monitorexit) в текущем потоке. Если исключение не возникает, значение извлекается из стека операндов текущей рамки (§2.6) и помещается в стек операндов рамки вызывающего метода. Все остальные значения в стеке операндов текущего метода отбрасываются.
Затем интерпретатор возвращает управление вызывающему методу, восстанавливая рамку вызывающего метода.
Исключения во время выполнения
Если реализация Java Virtual Machine не соблюдает правила структурной блокировки, описанные в §2.11.10, то если текущий метод является методом synchronized и текущий поток не является владельцем монитора, вошедшего или повторно вошедшего во время вызова метода, ireturn генерирует исключение IllegalMonitorStateException. Это может произойти, например, если метод synchronized содержит инструкцию monitorexit, но не инструкцию monitorenter, для объекта, на котором синхронизирован метод.
В противном случае, если реализация Java Virtual Machine соблюдает правила структурной блокировки, описанные в §2.11.10, и если первое из этих правил нарушено во время вызова текущего метода, тогда ireturn генерирует исключение IllegalMonitorStateException.
ishl
Операция
Левый сдвиг int
Формат
ishl
Формы
ishl = 120 (0x78)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
И значение1, и значение2 должны быть типа int. Значения извлекаются из стека операндов. Вычисляется результат путем сдвига значение1 влево на s битовых позиций, где s — значение 5 младших битов значение2. Результат помещается в стек операндов.
Замечания
Это эквивалентно (даже при переполнении) умножению на 2 в степени s. Расстояние сдвига фактически используется всегда в диапазоне от 0 до 31 включительно, как если бы значение2 было подвергнуто поразрядному логическому И с маской 0x1f.
ishr
Операция
Арифметический сдвиг вправо int
Формат
ishr
Формы
ishr = 122 (0x7a)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
И значение1, и значение2 должны быть типа int. Значения извлекаются из стека операндов. Вычисляется результат путем сдвига значение1 вправо на s битовых позиций с расширением знака, где s — значение 5 младших битов значение2. Результат помещается в стек операндов.
Замечания
Результирующее значение равно floor(значение1 / 2s), где s — значение2 & 0x1f. Для неотрицательного значение1 это эквивалентно усечению int деления на 2 в степени s. Расстояние сдвига фактически используется всегда в диапазоне от 0 до 31 включительно, как если бы значение2 было подвергнуто поразрядному логическому И с маской 0x1f.
istore
Операция
Сохранение int в локальной переменной
Формат
istore
индекс
Формы
istore = 54 (0x36)
Стек операндов
..., значение →
...
Описание
индекс — беззнаковый байт, который должен быть индексом в массиве локальных переменных текущей рамки (§2.6). значение вверху стека операндов должно быть типа int. Оно извлекается из стека операндов, и значение локальной переменной по индексу индекс устанавливается равным значение.
Замечания
Инструкцию istore можно использовать совместно с инструкцией wide (§wide) для доступа к локальной переменной с использованием двубайтного беззнакового индекса.
istore_
Операция
Сохранить int в локальной переменной
Формат
istore_
Формы
istore_0 = 59 (0x3b)
istore_1 = 60 (0x3c)
istore_2 = 61 (0x3d)
istore_3 = 62 (0x3e)
Стек операндов
..., значение →
...
Описание
<n> должен быть индексом в массиве локальных переменных текущей рамки (§2.6). значение вверху стека операндов должно быть типа int. Оно извлекается из стека операндов, и значение локальной переменной в позиции <n> устанавливается в значение.
Примечания
Каждая из инструкций istore_
isub
Операция
Вычесть int
Формат
isub
Формы
isub = 100 (0x64)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа int. Значения извлекаются из стека операндов. int результат равен значение1 - значение2. результат помещается в стек операндов.
При вычитании int, a-b даёт тот же результат, что и a+(-b). Для int значений вычитание из нуля равно отрицанию.
Результат — 32 младших бита истинного математического результата в формате двухдополнительного кода достаточной ширины, представленного как значение типа int. Если произошел переполнение, то знак результата может не совпадать со знаком математической разницы двух значений.
Несмотря на то, что переполнение может произойти, выполнение инструкции isub никогда не приводит к исключению во время выполнения.
iushr
Операция
Логическое правое сдвиг int
Формат
iushr
Формы
iushr = 124 (0x7c)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа int. Значения извлекаются из стека операндов. Вычисляется int результат путём сдвига значение1 вправо на s позиций в битах с расширением нулями, где s — значение 5 младших битов значение2. результат помещается в стек операндов.
Примечания
Если значение1 положительно, а s равно значение2 & 0x1f, результат совпадает с результатом значение1 >> s; если значение1 отрицательно, результат равен значению выражения (значение1 >> s) + (2 << ~s). Сложение члена (2 << ~s) компенсирует распространяемый знак. Расстояние сдвига фактически используется всегда в диапазоне от 0 до 31 включительно.
ixor
Операция
Булево XOR int
Формат
ixor
Формы
ixor = 130 (0x82)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа int. Они извлекаются из стека операндов. int результат вычисляется как побитовое исключающее ИЛИ значение1 и значение2. результат помещается в стек операндов.
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 младших битов значения long и отбрасывания 32 старших битов. Результат помещается в стек операндов.
Примечания
Инструкция l2i выполняет сужающее примитивное преобразование (JLS §5.1.3). Она может потерять информацию о величине значения. Результат также может иметь другой знак, чем значение.
ladd
Операция
Сложить long
Формат
ladd
Формы
ladd = 97 (0x61)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
значение1 и значение2 должны быть типа long. Значения извлекаются из стека операндов. Результат — это значение1 + значение2. Результат помещается в стек операндов.
Результат — это 64 младших бита истинного математического результата в формате дополнения до двух достаточной ширины, представленного как значение типа long. При переполнении знак результата может не совпадать со знаком математической суммы двух значений.
Несмотря на то, что переполнение может произойти, выполнение инструкции ladd никогда не генерирует исключение во время выполнения.
laload
Операция
Загрузка long из массива
Формат
laload
Формы
laload = 47 (0x2f)
Стек операндов
..., ссылка_на_массив, индекс →
..., значение
Описание
ссылка_на_массив должна быть типа reference и ссылаться на массив, элементы которого имеют тип long. Индекс должен быть типа int. Ссылка_на_массив и индекс извлекаются из стека операндов. Значение в элементе массива по индексу извлекается и помещается в стек операндов.
Исключения во время выполнения
Если ссылка_на_массив null, laload генерирует исключение NullPointerException.
В противном случае, если индекс не находится в пределах границ массива, на который ссылается ссылка_на_массив, laload генерирует исключение ArrayIndexOutOfBoundsException.
land
Операция
Логическое И long
Формат
land
Формы
land = 127 (0x7f)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
значение1 и значение2 должны быть типа long. Они извлекаются из стека операндов. Результат вычисляется путём побитового И значение1 и значение2. Результат помещается в стек операндов.
lastore
Операция
Сохранить в массив long
Формат
lastore
Формы
lastore = 80 (0x50)
Стек операндов
..., arrayref, index, value →
...
Описание
arrayref должен быть типа reference и должен ссылаться на массив, компоненты которого имеют тип long. index должен быть типа int, а value - типа long. arrayref, index и value извлекаются из стека операндов. Значение value сохраняется в качестве компонента массива по индексу index.
Исключения во время выполнения
Если arrayref является null, lastore генерирует исключение NullPointerException.
В противном случае, если index не находится в границах массива, на который ссылается arrayref, инструкция lastore генерирует исключение ArrayIndexOutOfBoundsException.
lcmp
Операция
Сравнение long
Формат
lcmp
Формы
lcmp = 148 (0x94)
Стек операндов
..., value1, value2 →
..., result
Описание
value1 и value2 должны быть типа long. Они оба извлекаются из стека операндов, и выполняется сравнение целых чисел со знаком. Если value1 больше value2, на стек операндов помещается значение 1. Если value1 равно value2, на стек операндов помещается значение 0. Если value1 меньше value2, на стек операндов помещается значение -1.
lconst_<l>
Операция
Поместить константу long
Формат
lconst_<l>
Формы
lconst_0 = 9 (0x9)
lconst_1 = 10 (0xa)
Стек операндов
... →
..., <l>
Описание
Поместить константу long <l> (0 или 1) на стек операндов.
ldc
Операция
Положить элемент из постоянного пула времени выполнения
Формат
ldc
индекс
Формы
ldc = 18 (0x12)
Стек операндов
... →
..., значение
Описание
Индекс — это беззнаковый байт, который должен быть допустимым индексом в постоянном пуле времени выполнения текущего класса (§2.6). Элемент постоянного пула времени выполнения по индексу должен быть константой времени выполнения типа int или float, или ссылкой на строковый литерал, или символьной ссылкой на класс, метод, тип метода или обработчик методов (§5.1).
Если элемент постоянного пула времени выполнения является константой времени выполнения типа int или float, то числовое значение этой константы кладётся в стек операндов в качестве int или float соответственно.
В противном случае, если элемент постоянного пула времени выполнения является ссылкой на экземпляр класса String, представляющий строковый литерал (§5.1), то ссылка на этот экземпляр, значение, кладётся в стек операндов.
В противном случае, если элемент постоянного пула времени выполнения является символьной ссылкой на класс (§5.1), то имя класса разрешается (§5.4.3.1), и ссылка на объект Class, представляющий этот класс, значение, кладётся в стек операндов.
В противном случае, элемент постоянного пула времени выполнения должен быть символьной ссылкой на тип метода или обработчик метода (§5.1). Тип метода или обработчик метода разрешаются (§5.4.3.5) и ссылка на полученный экземпляр java.lang.invoke.MethodType или java.lang.invoke.MethodHandle, значение, кладётся в стек операндов.
Исключения при связывании
При разрешении символьной ссылки на класс могут быть выброшены любые исключения, связанные с разрешением класса (§5.4.3.1).
При разрешении символьной ссылки на тип метода или обработчик метода могут быть выброшены любые исключения, связанные с разрешением типа метода или обработчика метода (§5.4.3.5).
ldc_w
Операция
Положить элемент из постоянного пула времени выполнения (индекс расширенного размера)
Формат
ldc_w
indexbyte1
indexbyte2
Формы
ldc_w = 19 (0x13)
Стек операндов
... →
..., значение
Описание
Беззнаковые indexbyte1 и indexbyte2 собираются в беззнаковый 16-битный индекс в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса рассчитывается как (indexbyte1 << 8) | indexbyte2. Индекс должен быть допустимым индексом в постоянном пуле времени выполнения текущего класса. Элемент постоянного пула времени выполнения по данному индексу должен быть константой времени выполнения типа int или float, или ссылкой на строковый литерал, или символьной ссылкой на класс, тип метода или обработчик метода (§5.1).
Если элемент постоянного пула времени выполнения является константой времени выполнения типа int или float, то числовое значение этой константы кладётся в стек операндов в качестве int или float соответственно.
В противном случае, если элемент постоянного пула времени выполнения является ссылкой на экземпляр класса String, представляющий строковый литерал (§5.1), то ссылка на этот экземпляр, значение, кладётся в стек операндов.
В противном случае, если элемент постоянного пула времени выполнения — символьная ссылка на класс (§4.4.1). Название класса разрешается (§5.4.3.1) и ссылка на объект Class, представляющий этот класс, значение, кладётся в стек операндов.
В противном случае, элемент постоянного пула времени выполнения должен быть символьной ссылкой на тип метода или обработчик метода (§5.1). Тип метода или обработчик метода разрешаются (§5.4.3.5) и ссылка на полученный экземпляр java.lang.invoke.MethodType или java.lang.invoke.MethodHandle, значение, кладётся в стек операндов.
Исключения при связывании
При разрешении символьной ссылки на класс могут быть выброшены любые исключения, связанные с разрешением класса (§5.4.3.1).
При разрешении символьной ссылки на тип метода или обработчик метода могут быть выброшены любые исключения, связанные с разрешением типа метода или обработчика метода (§5.4.3.5).
Примечания
Инструкция ldc_w идентична инструкции ldc (§ldc) за исключением более широкого индекса постоянного пула времени выполнения.
Инструкция ldc_w может использоваться только для помещения значения типа float, взятого из набора значений плавающей точки (§2.3.2), потому что константа типа float в постоянном пуле (§4.4.4) должна быть взята из набора значений плавающей точки.
ldc2_w
Операция
Поместить long или double из пула констант во время выполнения (широкий индекс)
Формат
ldc2_w
indexbyte1
indexbyte2
Формы
ldc2_w = 20 (0x14)
Стек операндов
... →
..., value
Описание
Беззнаковые indexbyte1 и indexbyte2 собираются в беззнаковый 16-битный индекс в пул констант текущего класса (§2.6), где значение индекса вычисляется как (indexbyte1 << 8) | indexbyte2. Индекс должен быть допустимым индексом в пуле констант текущего класса. Элемент пула констант по данному индексу должен быть константой типа long или double (§5.1). Численное значение value этой константы помещается в стек операндов как long или double, соответственно.
Примечания
Существует только широкоиндексная версия инструкции ldc2_w; нет инструкции ldc2, которая помещает long или double с индексом в один байт.
Инструкция ldc2_w может использоваться только для помещения значения типа double из набора значений с двойной точностью (§2.3.2), потому что константа типа double в пуле констант (§4.4.5) должна быть взята из набора значений с двойной точностью.
ldiv
Операция
Деление long
Формат
ldiv
Формы
ldiv = 109 (0x6d)
Стек операндов
..., value1, value2 →
..., result
Описание
И value1, и value2 должны быть типа long. Значения извлекаются из стека операндов. Результат result — это значение выражения языка программирования Java value1 / value2. Результат помещается в стек операндов.
Операция деления округляется до ближайшего целого числа; то есть, частное, полученное для значений n / d в long — это значение q с наибольшим возможным модулем, удовлетворяющее условию |d ⋅ q| ≤ |n|. Кроме того, q положительно, когда |n| ≥ |d| и n и d имеют одинаковый знак, но q отрицательно, когда |n| ≥ |d| и n и d имеют противоположные знаки.
Существует один особый случай, который не удовлетворяет этому правилу: если делимое — это отрицательное целое число с наибольшим возможным модулем для типа long, а делитель — -1, то происходит переполнение, и результат равен делимому; несмотря на переполнение, в этом случае исключение не выбрасывается.
Исключение во время выполнения
Если значение делителя в операции long деления равно 0, ldiv выбрасывает исключение ArithmeticException.
lload
Операция
Загрузка long из локальной переменной
Формат
lload
index
Формы
lload = 22 (0x16)
Стек операндов
... →
..., value
Описание
index — это беззнаковый байт. И index, и index+1 должны быть индексами в массиве локальных переменных текущего фрейма (§2.6). Локальная переменная по индексу index должна содержать long. Значение локальной переменной по индексу index помещается в стек операндов.
Примечания
Код lload может использоваться совместно с инструкцией wide (§wide) для доступа к локальной переменной с помощью двухбайтного беззнакового индекса.
lload_
Операция
Загрузка long из локальной переменной
Формат
lload_
Формы
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_
lmul
Операция
Умножение long
Формат
lmul
Формы
lmul = 105 (0x69)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа long. Значения извлекаются из стека операндов. Результат результат равен значение1 * значение2. Результат помещается в стек операндов.
Результат — 64 младших бита истинного математического результата в формате с достаточной шириной и дополнением до двух, представленный как значение типа long. Если происходит переполнение, знак результата может не совпадать со знаком математического произведения двух значений.
Несмотря на то, что может произойти переполнение, выполнение инструкции lmul никогда не вызывает исключения во время выполнения.
lneg
Операция
Отрицание long
Формат
lneg
Формы
lneg = 117 (0x75)
Стек операндов
..., значение →
..., результат
Описание
значение должно быть типа long. Оно извлекается из стека операндов. Результат результат — арифметическое отрицание значение, -значение. Результат помещается в стек операндов.
Для значений с long отрицание равно вычитанию из нуля. Так как виртуальная машина Java использует представление чисел в дополнительном коде, а диапазон значений в дополнительном коде несимметричен, отрицание максимального отрицательного long приводит к тому же максимальному отрицательному числу. Несмотря на то, что произошло переполнение, исключение не генерируется.
Для всех значений long x, -x равно (~x)+1.
lookupswitch
Операция
Обращение к таблице переходов по совпадению ключа и переход
Формат
lookupswitch
<0-3 байта заполнения>
defaultbyte1
defaultbyte2
defaultbyte3
defaultbyte4
npairs1
npairs2
npairs3
npairs4
пар match-offset...
Формы
lookupswitch = 171 (0xab)
Стек операндов
..., ключ →
...
Описание
Инструкция lookupswitch имеет переменную длину. Сразу после кода операции lookupswitch должно быть от нуля до трёх байтов заполнения, таким образом, чтобы defaultbyte1 начинался по адресу, кратно четырём байтам от начала текущего метода (кода операции первой инструкции). Сразу после заполнения следуют ряд знаковых 32-битных значений: default, npairs, а затем npairs пар знаковых 32-битных значений. npairs должно быть больше или равно 0. Каждая из npairs пар состоит из int match и знакового 32-битного offset. Каждое из этих знаковых 32-битных значений строится из четырёх беззнаковых байтов как (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4.
Таблица match-offset пар инструкции lookupswitch должна быть отсортирована по возрастанию match.
Ключ должен быть типа int и извлекается из стека операндов. Ключ сравнивается со значениями match. Если он равен одному из них, то адрес назначения вычисляется путем добавления соответствующего offset к адресу кода операции этой инструкции lookupswitch. Если ключ не совпадает ни с одним из значений match, то адрес назначения вычисляется путем добавления default к адресу кода операции этой инструкции lookupswitch. Затем выполнение продолжается по адресу назначения.
Адрес назначения, который может быть вычислен из offset каждой пары match-offset, а также вычисленный из default, должен быть адресом кода операции инструкции внутри метода, содержащего эту инструкцию lookupswitch.
Примечания
Требуемая выравнивание 4-байтовых операндов инструкции lookupswitch гарантирует выравнивание этих операндов по 4 байта только в том случае, если метод, содержащий lookupswitch, расположен на границе в 4 байта.
Пары match-offset отсортированы для поддержки процедур поиска, которые быстрее, чем линейный поиск.
lor
Операция
Булево ИЛИ long
Формат
lor
Формы
lor = 129 (0x81)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа long. Они извлекаются из стека операндов. long результат вычисляется путем побитового включительно ИЛИ значение1 и значение2. Результат помещается в стек операндов.
lrem
Операция
Остаток long
Формат
lrem
Формы
lrem = 113 (0x71)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
Оба значение1 и значение2 должны быть типа long. Значения извлекаются из стека операндов. long результат равен значение1 - (значение1 / значение2) * значение2. Результат помещается в стек операндов.
Результат инструкции lrem таков, что (a/b)*b + (a%b) равно a. Это тождество выполняется даже в особом случае, когда делимое является отрицательным long наибольшего возможного значения для своего типа, а делитель равен -1 (остаток равен 0). Из этого правила следует, что результат операции остатка может быть отрицательным только если делимое отрицательное и может быть положительным только если делимое положительное; кроме того, величина результата всегда меньше величины делителя.
Исключение во время выполнения
Если значение делителя для операции остатка long равно 0, lrem выбрасывает ArithmeticException.
lreturn
Операция
Возврат значения long из метода
Формат
lreturn
Формы
lreturn = 173 (0xad)
Стек операндов
..., значение →
[пустой]
Описание
Текущий метод должен иметь возвращаемый тип 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)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
значение1 должно быть типа long, а значение2 — типа int. Значения извлекаются из стека операндов. Вычисляется long результат путём сдвига значение1 влево на s позиций, где s — 6 младших битов значение2. Результат помещается в стек операндов.
Примечания
Это эквивалентно (даже при переполнении) умножению на 2 в степени s. Используемое расстояние сдвига всегда находится в диапазоне от 0 до 63 включительно, как если бы значение2 подвергалось побитовому логическому И с маской 0x3f.
lshr
Операция
Арифметический сдвиг вправо long
Формат
lshr
Формы
lshr = 123 (0x7b)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
значение1 должно быть типа long, а значение2 — типа int. Значения извлекаются из стека операндов. Вычисляется long результат путём сдвига значение1 вправо на s позиций со знаком, где s — значение 6 младших битов значение2. Результат помещается в стек операндов.
Примечания
Результирующее значение равно floor(значение1 / 2s), где s равно значение2 & 0x3f. Для неотрицательного значение1 это эквивалентно усечению long деления на 2 в степени s. Используемое расстояние сдвига всегда находится в диапазоне от 0 до 63 включительно, как если бы значение2 подвергалось побитовому логическому И с маской 0x3f.
lstore
Операция
Сохранить long в локальную переменную
Формат
lstore
индекс
Формы
lstore = 55 (0x37)
Стек операндов
..., значение →
...
Описание
индекс — это беззнаковый байт. индекс и индекс+1 должны быть индексами в массиве локальных переменных текущей рамки (§2.6). значение в верхней части стека операндов должно быть типа long. Оно извлекается из стека операндов, и локальные переменные по индексу индекс и индекс+1 устанавливаются в значение.
Примечания
Инструкция lstore может быть использована совместно с инструкцией wide (§wide) для доступа к локальной переменной с использованием двухбайтового беззнакового индекса.
lstore_
Операция
Сохранить long в локальную переменную
Формат
lstore_
Формы
lstore_0 = 63 (0x3f)
lstore_1 = 64 (0x40)
lstore_2 = 65 (0x41)
lstore_3 = 66 (0x42)
Стек операндов
..., значение →
...
Описание
И <n>, и <n>+1 должны быть индексами в массиве локальных переменных текущей рамки (§2.6). Значение на вершине стека операндов должно быть типа long. Оно извлекается из стека операндов, а локальные переменные в <n> и <n>+1 устанавливаются в значение.
Примечания
Каждая из инструкций lstore_
lsub
Операция
Вычитание long
Формат
lsub
Формы
lsub = 101 (0x65)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
И значение1, и значение2 должны быть типа long. Значения извлекаются из стека операндов. long результат равен значение1 - значение2. Результат помещается в стек операндов.
Для long вычитания, a-b даёт тот же результат, что и a+(-b). Для long значений, вычитание из нуля то же самое, что и отрицание.
Результат — 64 младших бита истинного математического результата в достаточно широком формате дополнения до двух, представленного в виде значения типа long. Если произойдёт переполнение, то знак результата может не совпадать со знаком математической разницы двух значений.
Несмотря на то, что может произойти переполнение, выполнение инструкции lsub никогда не вызывает исключения во время выполнения.
lushr
Операция
Логический сдвиг вправо long
Формат
lushr
Формы
lushr = 125 (0x7d)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
значение1 должно быть типа long, а значение2 — типа int. Значения извлекаются из стека операндов. Вычисляется long результат с помощью логического сдвига значение1 вправо на s позиций разряда, с расширением до нуля, где s — значение 6 младших битов значение2. Результат помещается в стек операндов.
Примечания
Если значение1 положительно и s равно значение2 & 0x3f, результат совпадает с значение1 >> s; если значение1 отрицательно, результат равен значению выражения (значение1 >> s) + (2L << ~s). Добавление (2L << ~s) устраняет распространяемый разряд знака. Расстояние сдвига, фактически используемое, всегда в диапазоне от 0 до 63 включительно.
lxor
Операция
Булево XOR long
Формат
lxor
Формы
lxor = 131 (0x83)
Стек операндов
..., значение1, значение2 →
..., результат
Описание
И значение1, и значение2 должны быть типа long. Они извлекаются из стека операндов. long результат вычисляется как побитовое исключающее ИЛИ значение1 и значение2. Результат помещается в стек операндов.
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, как если бы использовались monitorenter и monitorexit.
Связывание монитора с объектом может осуществляться различными способами, выходящими за рамки данного спецификации. Например, монитор может быть выделен и освобождён одновременно с объектом. В качестве альтернативы, он может быть динамически выделен в тот момент, когда поток пытается получить исключительный доступ к объекту, и освобождён в более позднее время, когда ни один поток не остаётся в мониторе для объекта.
Конструкции синхронизации языка программирования Java требуют поддержки операций над мониторами помимо входа и выхода. К ним относятся ожидание монитора (Object.wait) и уведомление других потоков, ожидающих монитора (Object.notifyAll и Object.notify). Эти операции поддерживаются в стандартном пакете java.lang, поставляемом с виртуальной машиной Java. Явное подтверждение этих операций отсутствует в наборе инструкций виртуальной машины Java.
monitorexit
Операция
Выход из монитора для объекта
Формат
monitorexit
Формы
monitorexit = 195 (0xc3)
Стек операндов
..., objectref →
...
Описание
objectref должен быть типа reference.
Поток, выполняющий monitorexit, должен быть владельцем монитора, связанного с экземпляром, на который ссылается objectref.
Поток уменьшает счётчик входов в монитор, связанный с objectref. Если в результате значение счётчика входов становится нулём, поток выходит из монитора и больше не является его владельцем. Другие потоки, блокированные для входа в монитор, могут попытаться сделать это.
Исключения во время выполнения
Если objectref является null, monitorexit выбрасывает исключение NullPointerException.
В противном случае, если поток, выполняющий monitorexit, не является владельцем монитора, связанного с экземпляром, на который ссылается objectref, monitorexit выбрасывает исключение IllegalMonitorStateException.
В противном случае, если реализация виртуальной машины Java применяет правила структурированной блокировки, описанные в §2.11.10, и если второе из этих правил нарушается выполнением этой инструкции monitorexit, то monitorexit выбрасывает исключение IllegalMonitorStateException.
Примечания
Одна или несколько инструкций monitorexit могут быть использованы с инструкцией monitorenter (§monitorenter) для реализации оператора synchronized на языке программирования Java (§3.14). Инструкции monitorenter и monitorexit не используются в реализации методов synchronized, хотя они могут использоваться для обеспечения эквивалентной семантики блокировки.
Виртуальная машина Java поддерживает исключения, сгенерированные внутри методов synchronized и операторов synchronized, по-разному:
-
Выход из монитора при нормальном завершении метода
synchronizedобрабатывается инструкциями возврата виртуальной машины Java. Выход из монитора при внезапном завершении методаsynchronizedнеявно обрабатывается инструкцией athrow виртуальной машины Java. -
Когда исключение выбрасывается внутри оператора
synchronized, выход из монитора, вошедшего до выполнения оператораsynchronized, достигается с помощью механизма обработки исключений виртуальной машины Java (§3.14).
multianewarray
Операция
Создание многомерного массива
Формат
multianewarray
indexbyte1
indexbyte2
dimensions
Формы
multianewarray = 197 (0xc5)
Стек операндов
..., count1, [count2, ...] →
..., arrayref
Описание
Операнд dimensions — это беззнаковый байт, который должен быть больше или равен 1. Он представляет количество измерений создаваемого массива. Стек операндов должен содержать dimensions значений. Каждое такое значение представляет количество компонентов в измерении создаваемого массива, должно быть типа int и должно быть неотрицательным. count1 — желаемая длина в первом измерении, count2 — во втором и т. д.
Все значения count извлекаются со стека операндов. Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на тип класса, массива или интерфейса. Названный тип класса, массива или интерфейса разрешается (§5.4.3.1). Результирующий элемент должен быть типом массива с размерностью, большей или равной dimensions.
Многомерный массив нового типа выделяется из кучи сборщика мусора. Если какое-либо значение count равно нулю, последующие измерения не выделяются. Компоненты массива в первом измерении инициализируются подмассивами типа второго измерения и так далее. Компоненты последнего выделенного измерения массива инициализируются значением по умолчанию (§2.3, §2.4) для типа элемента типа массива. Ссылка reference 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.
В противном случае, если символическая ссылка на класс, массив или тип интерфейса разрешается на интерфейс или является abstract классом, new выбросит InstantiationError.
Исключение во время выполнения
В противном случае, если выполнение этой инструкции new вызывает инициализацию ссылаемого класса, new может выбросить Error, как подробно описано в JLS §15.9.4.
Примечания
Инструкция new не полностью создаёт новый экземпляр; создание экземпляра не завершается до тех пор, пока метод инициализации экземпляра (§2.9) не будет вызван на неинициализированном экземпляре.
newarray
Операция
Создать новый массив
Формат
newarray
atype
Формы
newarray = 188 (0xbc)
Стек операндов
..., count →
..., arrayref
Описание
Значение count должно быть типа int. Оно извлекается из стека операндов. count представляет количество элементов в создаваемом массиве.
atype — код, указывающий тип создаваемого массива. Он должен принимать одно из следующих значений:
Таблица 6.5.newarray-A. Коды типов массивов
| Тип массива | atype |
|---|---|
T_BOOLEAN | 4 |
T_CHAR | 5 |
T_FLOAT | 6 |
T_DOUBLE | 7 |
T_BYTE | 8 |
T_SHORT | 9 |
T_INT | 10 |
T_LONG | 11 |
Создается новый массив, компоненты которого имеют тип atype и длину count, выделяемый из управляемой сборкой мусора кучи. В стек операндов помещается ссылка arrayref на этот новый объект массива. Каждый элемент нового массива инициализируется значением по умолчанию (§2.3, §2.4) для типа элементов типа массива.
Исключение во время выполнения
Если count меньше нуля, newarray генерирует исключение NegativeArraySizeException.
Примечания
В реализации Java Virtual Machine Oracle массивы типа boolean (atype — T_BOOLEAN) хранятся как массивы 8-битных значений и обрабатываются инструкциями baload и bastore (§baload, §bastore), которые также обращаются к массивам типа byte. Другие реализации могут реализовывать упакованные массивы boolean; инструкции baload и bastore должны по-прежнему использоваться для доступа к этим массивам.
nop
Операция
Ничего не делать
Формат
nop
Формы
nop = 0 (0x0)
Стек операндов
Без изменений
Описание
Ничего не делать.
pop
Операция
Извлечь значение из вершины стека операндов
Формат
pop
Формы
pop = 87 (0x57)
Стек операндов
..., value →
...
Описание
Извлечь верхнее значение из стека операндов.
Инструкция pop не должна использоваться, если value не является значением вычислительного типа категории 1 (§2.11.1).
pop2
Операция
Извлечь одно или два верхних значения из стека операндов
Формат
pop2
Формы
pop2 = 88 (0x58)
Стек операндов
Форма 1:
..., value2, value1 →
...
где каждое из value1 и value2 — значение вычислительного типа категории 1 (§2.11.1).
Форма 2:
..., value →
...
где value — значение вычислительного типа категории 2 (§2.11.1).
Описание
Извлечь одно или два значения с вершины стека операндов.
putfield
Операция
Установить поле в объекте
Формат
putfield
indexbyte1
indexbyte2
Формы
putfield = 181 (0xb5)
Стек операндов
..., objectref, value →
...
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на поле (§5.1), которая содержит имя и дескриптор поля, а также символическую ссылку на класс, в котором это поле находится. Класс objectref не должен быть массивом. Если поле является protected, и оно является членом суперкласса текущего класса, и поле не объявлено в той же группе времени выполнения (§5.3), что и текущий класс, то класс objectref должен быть либо текущим классом, либо подклассом текущего класса.
Ссылка на поле разрешается (§5.4.3.2). Тип значения value, хранимого инструкцией putfield, должен быть совместим с дескриптором разрешённого поля (§4.3.2). Если тип дескриптора поля является boolean, byte, char, short или int, то value должно быть int. Если тип дескриптора поля является float, long или double, то value должно быть float, long или double соответственно. Если тип дескриптора поля является типом ссылки, то value должно быть типа, совместимого с типом дескриптора поля (JLS §5.2). Если поле является final, оно должно быть объявлено в текущем классе, и инструкция должна находиться в методе инициализации экземпляра (<init>) текущего класса (§2.9).
value и objectref извлекаются из стека операндов. objectref должен быть типа reference. value преобразуется в значение value' (§2.8.3), и связанное поле в objectref устанавливается в value'.
Исключения связи
При разрешении символической ссылки на поле могут быть выброшены исключения, связанные с разрешением поля (§5.4.3.2).
В противном случае, если разрешённое поле является static полем, putfield выбрасывает исключение IncompatibleClassChangeError.
В противном случае, если поле является final, оно должно быть объявлено в текущем классе, и инструкция должна находиться в методе инициализации экземпляра (<init>) текущего класса. В противном случае выбрасывается исключение IllegalAccessError.
Исключение времени выполнения
В противном случае, если objectref является null, инструкция putfield выбрасывает исключение NullPointerException.
putstatic
Операция
Установить статическое поле в классе
Формат
putstatic
indexbyte1
indexbyte2
Формы
putstatic = 179 (0xb3)
Стек операндов
..., значение →
...
Описание
Беззнаковые indexbyte1 и indexbyte2 используются для построения индекса в постоянном пуле времени выполнения текущего класса (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Элемент постоянного пула времени выполнения по этому индексу должен быть символической ссылкой на поле (§5.1), которая предоставляет имя и дескриптор поля, а также символическую ссылку на класс или интерфейс, в котором находится поле. Ссылаемое поле разрешается (§5.4.3.2).
При успешном разрешении поля, класс или интерфейс, которые объявили разрешенное поле, инициализируются (§5.5), если этот класс или интерфейс еще не были инициализированы.
Тип значения, хранящегося инструкцией putstatic, должен быть совместим с дескриптором ссылаемого поля (§4.3.2). Если тип дескриптора поля это boolean, byte, char, short или int, то значение должно быть int. Если тип дескриптора поля это float, long или double, то значение должно быть float, long или double, соответственно. Если тип дескриптора поля — тип ссылки, то значение должно быть типа, совместимого с типом дескриптора поля (JLS §5.2). Если поле является final, оно должно быть объявлено в текущем классе, а инструкция должна находиться в методе <clinit> текущего класса (§2.9).
Значение извлекается из стека операндов и подвергается преобразованию множества значений (§2.8.3), в результате чего получается значение'. Поле класса устанавливается в значение'.
Исключения связывания
Во время разрешения символической ссылки на поле класса или интерфейса может быть выброшено любое из исключений, относящихся к разрешению поля (§5.4.3.2).
В противном случае, если разрешенное поле не является полем класса (класса) или интерфейсом, putstatic выбрасывает исключение IncompatibleClassChangeError.
В противном случае, если поле является final, оно должно быть объявлено в текущем классе, а инструкция должна находиться в методе <clinit> текущего класса. В противном случае выбрасывается исключение IllegalAccessError.
Исключение времени выполнения
В противном случае, если выполнение этой инструкции putstatic приводит к инициализации ссылаемого класса или интерфейса, putstatic может выбросить исключение Error, как подробно описано в §5.5.
Примечания
Инструкция putstatic может использоваться только для установки значения поля интерфейса при инициализации этого поля. К полям интерфейса можно обращаться только один раз, во время выполнения выражения инициализации переменной интерфейса при инициализации интерфейса (§5.5, JLS §9.3.1).
ret
Операция
Возврат из подпрограммы
Формат
ret
index
Формы
ret = 169 (0xa9)
Стек операндов
Без изменений
Описание
index — беззнаковый байт от 0 до 255 включительно. Локальная переменная в текущем фрейме (§2.6) по индексу index должна содержать значение типа returnAddress. Содержимое локальной переменной записывается в регистр pc виртуальной машины Java, и выполнение продолжается оттуда.
Примечания
Обратите внимание, что jsr (§jsr) помещает адрес в стек операндов, а ret извлекает его из локальной переменной. Эта асимметрия является намеренной.
В реализации компилятора 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 извлекаются из стека операндов. int 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 могут следовать от нуля до трёх байтов заполнителя, так что defaultbyte1 начинается по адресу, кратно четырём байтам с начала текущего метода (кода первой инструкции). Сразу после заполнителя следуют байты, представляющие три целых 32-битных значения: default, low и high. Сразу за ними следуют байты, представляющие серию high - low + 1 целых 32-битных смещений. Значение low должно быть меньше или равно high. high - low + 1 целых 32-битных смещений рассматриваются как таблица переходов с индексом 0. Каждое из этих целых 32-битных значений строится как (byte1 << 24) | (byte2 << 16) | (byte3 << 8) | byte4.
Значение индекс должно быть типа int и извлекается из стека операндов. Если индекс меньше low или индекс больше high, то адрес назначения вычисляется путем добавления default к адресу кода операции этой инструкции tableswitch. В противном случае извлекается смещение в позиции индекс - low таблицы переходов. Адрес назначения вычисляется путем добавления этого смещения к адресу кода операции этой инструкции tableswitch. Затем выполнение продолжается по адресу назначения.
Адрес назначения, который может быть вычислен из каждого смещения таблицы переходов, а также из default, должен быть адресом кода инструкции внутри метода, содержащего эту инструкцию tableswitch.
Примечания
Требуемое выравнивание 4-байтовых операндов инструкции tableswitch гарантирует выравнивание этих операндов по 4 байтам, только если метод, содержащий tableswitch, начинается на границе 4 байт.
wide
Операция
Увеличить индекс локальной переменной на дополнительные байты
Формат 1
wide
<opcode>
indexbyte1
indexbyte2
где <opcode> — один из iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore или ret
Формат 2
wide
iinc
indexbyte1
indexbyte2
constbyte1
constbyte2
Формы
wide = 196 (0xc4)
Стек операндов
Такой же, как у модифицированной инструкции
Описание
Инструкция wide изменяет поведение другой инструкции. Она имеет два формата, зависящих от модифицируемой инструкции. Первый формат инструкции wide изменяет одну из инструкций iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore или ret (§iload, §fload, §aload, §lload, §dload, §istore, §fstore, §astore, §lstore, §dstore, §ret). Второй формат применяется только к инструкции iinc (§iinc).
В любом случае, за самим кодом операции wide в скомпилированном коде следует код инструкции, которую wide модифицирует. В обоих форматах двум беззнаковым байтам indexbyte1 и indexbyte2 следуют модифицированные коды операции, и они собираются в 16-битный беззнаковый индекс локальной переменной в текущей рамке (§2.6), где значение индекса равно (indexbyte1 << 8) | indexbyte2. Вычисленный индекс должен быть индексом в массиве локальных переменных текущей рамки. Где инструкция wide модифицирует инструкцию lload, dload, lstore или dstore, индекс, следующий за вычисленным индексом (индекс + 1), также должен быть индексом в массиве локальных переменных. Во втором формате два непосредственных беззнаковых байта constbyte1 и constbyte2 следуют за indexbyte1 и indexbyte2 в потоке кода. Эти байты также собираются в знаковое 16-битное значение константы, где константа равна (constbyte1 << 8) | constbyte2.
Расширенный байткод работает как обычно, за исключением использования более широкого индекса и, в случае второго формата, более широкого диапазона инкремента.
Примечания
Хотя мы говорим, что wide «изменяет поведение другой инструкции», инструкция wide фактически обрабатывает байты, составляющие модифицированную инструкцию, как операнды, изменяя встроенную инструкцию в процессе. В случае модифицированной инструкции iinc один из логических операндов iinc даже не находится в обычном смещении от кода операции. Встроенная инструкция никогда не должна выполняться напрямую; её код операции никогда не должен быть целью какой-либо инструкции передачи управления.
© Oracle and/or its affiliates. All rights reserved.
Licensed under the Oracle Technology Network License Agreement.