Список инструкций JVM с детальным описанием формата и действий, которые они выполняют
Список инструкций JVM с детальным описанием формата и действий, которые они выполняют - перевод на русский язык главы Спецификации виртуальной машины Java.
Перевод: Саянкин А.А.
aaload | aaload |
Операция | Загружает ссылку из массива |
Формат |
|
Формы | aaload = 50 (0x32) |
Стек операндов | ..., ссылка на массив, индекс → |
..., значение |
Описание | Значение ссылки на массив должно быть типа reference и должно ссылаться на массив, чьи компоненты также принадлежат типу reference. Значение индекса должно быть типа int. Как ссылка на массив так и индекс считываются из стека операндов. Значение типа reference считывается из элемента массива с индексом индекс и записывается в стек операндов. |
Исключения времени выполнения | Если значение ссылки на массив равно null, то инструкция aaload генерирует исключение NullPointerException. |
aastore | aastore |
Операция | Сохраняет ссылку (reference) из стека в массив |
Формат |
|
Формы | aastore= 83 (0x53) |
Стек операндов | ..., ссылка на массив, индекс, значение →
... |
Описание | Значение ссылки на массив должно быть типа reference и должно ссылаться на массив, чьи компоненты также принадлежат типу reference. Значение индекса должно быть типа int, значение должно быть типа reference. Значение, ссылка на массив и индекс считываются из стека операндов. Значение типа reference сохраняется в элементе массива с индексом индекс.
Во время выполнения тип значения должен быть совместим с типом компонентов массива, на который ссылается ссылка на массив. Присваивание ссылочного типа S (источник) типу T (приёмник) допустимо тогда и только тогда:
|
Исключения времени выполнения | Если ссылка на массив равна null, то инструкция aaload генерирует исключение NullPointerException.
В противном случае, если индекс вне границ массива, на который ссылается ссылка на массив, то aastore генерирует исключение ArrayIndexOutOfBoundsException. |
aconst_null | aconst_null |
Операция | Записывает в стек null |
Формат |
|
Формы | aconst_null= 1 (0x1) |
Стек операндов | ... →
..., null |
Описание | Записывает в стек операндов ссылку на null объект. |
Примечания | Виртуальная машина Java не определяет конкретного значения для null. |
aload | aload |
Операция | Загружает ссылку из локальной переменной в стек |
Формат |
|
Формы | aload = 25 (0x19) |
Стек операндов | ..., →
..., ссылка на объект |
Описание | Индекс представляет собой беззнаковый байт, который определяет локальную переменную текущего фрейма (§2.6). Локальная переменная с указанным индексом должна содержать значение типа reference. Ссылка на объект из локальной переменной записывается в стек операндов. |
Примечания | Инструкция aload не может быть использована для записи в стек операндов значений типа returnAddress из локальной переменной. Эта асимметрия с инструкцией astore сделана намеренно.
Инструкция aload может быть использована с инструкцией wide для доступа к локальным переменным, имеющим двухбайтовый индекс. |
aload_<n> | aload_<n> |
Операция | Загружает ссылку из локальной переменной в стек |
Формат |
|
Формы | aload_0= 42 (0x2a)
aload_1= 43 (0x2b) aload_2= 44 (0x2c) aload_3= 45 (0x2d) |
Стек операндов | ..., →
..., ссылка на объект |
Описание | Значение <n> должно быть индексом локальной переменной текущего фрейма (см. §2.6). Локальная переменная с индексом <n> должна содержать значение типа reference. Ссылка на объект, находящаяся в локальной переменной с индексом <n> записывается в стек операндов. |
Примечания | Инструкция aload_<n> не может быть использована для записи в стек операндов значений типа returnAddress из локальной переменной. Эта асимметрия с инструкцией astore_<n> сделана намеренно.
Каждая из инструкций aload_<n> выполняет то же, что и aload с явно заданным индексом. |
anewarray | anewarray |
Операция | Создаёт новый массив из ссылок |
Формат |
|
Формы | anewarray = 189 (0xbd) |
Стек операндов | ..., число элементов →
..., ссылка на массив |
Описание | Число элементов должно принадлежать типу int. Оно считывается из стека операндов. Число элементов определяет размер массива. Беззнаковые байт_индекса1 и байт_индекса2 используются для построения индекса массива в константном пуле времени выполнения текущего класса (см. §2.6). Значение индекса определяется как (байт_индекса1 << 8)|(байт_индекса2). Элемент константного пула, на который указывает построенный индекс, должен быть ссылкой на класс, массив или интерфейс. Обозначенный класс, массив или интерфейс разрешается (см. §5.4.3.1) и определяется тип элементов массива. В куче создаётся новый массив, с указанным типом элементов, заданной размерностью. Ссылка на созданный массив записывается в стек операндов. Все элементы инициализируются значениями null, которые являются значениями по умолчанию для типа reference (см. §2.4) |
Исключения связывания | Во время разрешения символьной ссылки на класс, массив или интерфейс, может быть создано любое исключение, описанное в (§5.4.3.1). |
Исключения времени выполнения | Если число элементов меньше нуля, инструкция anewarray генерирует NegativeArraySizeException. |
Примечания | Инструкция anewarray используется для создания одномерного массива ссылок на объекты или части многомерного массива. |
areturn | areturn |
Операция | Создаёт новый массив из ссылок |
Формат |
|
Формы | areturn= 176 (0xb0) |
Стек операндов | ..., ссылка на объект →
[пусто] |
Описание | Ссылка на объект должна принадлежать типу reference и должна ссылаться на объект, тип которого совместим по присвоению (см. JLS §5.2) с типом возвращаемого значения, заданным в дескрипторе текущего метода (см. §4.3.3). Если текущий метод объявлен как synchronized, то происходит захват (или повторный захват) монитора, при запуске метода, и освобождение монитора при выполнении areturn, так как если бы была выполнена инструкция monitorexit в текущем потоке. Если в ходе выполнения метода не было сгенерировано исключение, ссылка на объект считывается из стека операндов текущего фрейма (см. §2.6) и записывается в стек операндов вызывающего метода. Все значения в стеке операндов текущего фрейма теряются.
Интерпретатор восстанавливает вызывающий фрейм и передаёт управление вызвавшему методу. |
Исключения времени выполнения | Ссылка на объект должна принадлежать типу reference и должна ссылаться на объект, тип которого совместим по присвоению (см. JLS §5.2) с типом возвращаемого значения, заданным в дескрипторе текущего метода (см. §4.3.3). Если текущий метод объявлен как synchronized, то происходит захват (или повторный захват) монитора, при запуске метода, и освобождение монитора при выполнении areturn, так как если бы была выполнена инструкция monitorexit в текущем потоке. Если в ходе выполнения метода не было сгенерировано исключение, ссылка на объект считывается из стека операндов текущего фрейма (см. §2.6) и записывается в стек операндов вызывающего метода. Все значения в стеке операндов текущего фрейма теряются.
Интерпретатор восстанавливает вызывающий фрейм и передаёт управление вызвавшему методу. |
arraylength | arraylength |
Операция | Возвращает длину массива |
Формат |
|
Формы | arraylength= 190 (0xbe) |
Стек операндов | ..., ссылка на массив →
..., длина массива |
Описание | Ссылка на массив должна принадлежать типу reference. Она считывается из стека операндов. Определяется длина массива по указанной ссылке. Эта длина массива записывается в стек операндов как значение типа int. |
Исключения времени выполнения | Если ссылка на массив равна null, arraylength генерирует NullPointerException. |
astore | astore |
Операция | Считывает ссылку из стека и сохраняет в локальную переменную |
Формат |
|
Формы | astore= 58 (0x3a) |
Стек операндов | ..., ссылка на объект →
..., |
Описание | Индекс представляет собой беззнаковый байт, являющейся индексом локальной переменной текущего фрейма (см. §2.6). Ссылка на объект на вершине стека операндов должна принадлежать типу returnAddress или reference. Ссылка считывается из стека операндов и записывается в локальную переменную с заданным индексом. |
Примечания | Инструкция astore совместно со ссылкой типа returnAddress используется для реализации блока finally в языке программирования Java (см. §3.13).
Инструкция aload не может быть использована для загрузки значения типа returnAddress из локальной переменной в стек операндов. Эта асимметрия с astore сделана намеренно. Также astore может быть использована с инструкцией wide, которая расширяет значения индекса локальной переменной до двух байт. |
astore_<n> | astore_<n> |
Операция | Считывает ссылку из стека и сохраняет в локальную переменную |
Формат |
|
Формы | astore_0= 75 (0x4b)
astore_1= 76 (0x4c) astore_2= 77 (0x4d) astore_3= 78 (0x4e) |
Стек операндов | ..., ссылка на объект →
... |
Описание | <n> представляет собой беззнаковый байт, являющейся индексом локальной переменной текущего фрейма (см. §2.6). Ссылка на объект на вершине стека операндов должна принадлежать типу returnAddress или reference. Ссылка считывается из стека операндов и записывается в локальную переменную с заданным индексом <n>. |
Примечания | Инструкция astore_<n> совместно со ссылкой типа returnAddress используется для реализации блока finally в языке программирования Java (см. §3.13).
Инструкция aload_<n> не может быть использована для загрузки значения типа returnAddress из локальной переменной в стек операндов. Эта асимметрия с astore_<n> сделана намеренно. Каждая инструкция astore_<n> выполняет то же самое, что и инструкция astore с индексом равным <n>. |
athrow | athrow |
Операция | Выбрасывает исключение |
Формат |
|
Формы | athrow= 191 (0xbf) |
Стек операндов | ..., ссылка на объект→
ссылка на объект |
Описание | Ссылка на объект должна принадлежать типу reference и должна ссылаться на объект класса Throwable или его наследника. Она считывается из стека операндов. Затем в текущем методе (см. §2.6) первого подходящего обработчика по алгоритму, указанному в §2.10.
Если обработчик исключения соответствующий ссылке на объект (т.е. соответствующему исключению) был найден, то в нем находится ссылка на первую инструкцию кода, который должен быть выполнен. В регистр pc записывается адрес первой инструкции кода, стек операндов текущего фрейма очищается, ссылка на объект записывается обратно в стек и выполнение продолжается. Если обработчик не найден в текущем фрейме, текущий фрейм считывается из стека фреймов. Если текущий метод был объявлен как synchronized, захваченный при входе в метод монитор отпускается, как если была выполнена инструкция monitorexit. Фрейм вызывающего метода (если таковой существует) становится текущим и исключение выбрасывается повторно. Если такого фрейма нет, происходит выход из текущего потока. |
Исключения времени выполнения | Если ссылка на объект равна null, инструкция athrow генерирует NullPointerException.
В противном случае, если реализация виртуальной машины Java не поддерживает правила структурной блокировки, описанные в §2.11.10, тогда если метод текущего фрейма объявлен как synchronized и текущий поток не является владельцем монитора, захваченного при входе в метод, то генерируется исключение IllegalMonitorStateException вместо исключения выброшенного ранее. Это может произойти, если аварийно прерванный synchronized метод содержит инструкцию monitorexit, а соответствующей инструкции monitorenter для того же объекта синхронизации нет. Если реализация виртуальной машины Java поддерживает правила структурной блокировки, описанные в §2.11.10 и первое из этих правил нарушено во время вызова метода, тогда athrow генерирует IllegalMonitorStateException вместо выбрасываемого до этого исключения. |
Примечания | Описание стека операндов для инструкции athrow может сбивать с толку: если обработчик найден в текущем методе, инструкция athrow очищает стек операндов, а затем записывает в стек ссылку на выбрасываемое исключение. Однако, такое решение вполне приемлемо, поскольку, если соответствующего обработчика в текущем методе не найдено, то исключение будет выброшено далее по цепочке вызовов методов и если обработчик будет найден, стек будет очищен и ссылка на исключение помещена в стек. Все промежуточные фрейм из цепочки вызова методов, в которых обработчик не был найден, также будут очищены. |
baload | baload |
Операция | Загружает значение типа byte или boolean из массива в стек |
Формат |
|
Формы | baload = 51 (0x33) |
Стек операндов | ..., ссылка на массив, индекс →
..., значение |
Описание | Ссылка на массив должна принадлежать типу reference и ссылаться на массив, чьи компоненты являются типами byte или boolean. Индекс должен принадлежать типу int. Как ссылка на массив, так и индекс считываются из стека операндов. Значение типа byte считывается из элемента массива с заданным индексом, расширяется с учётом знака до типа int и записывается вершину стека операндов. |
Исключения времени выполнения | Если ссылка на массив равна null, то baload генерирует NullPointerException.
Если индекс вне границ массива, то baload генерирует ArrayIndexOutOfBoundsException. |
Примечания | Инструкция baload используется для получения значений из массивов как типа byte, так и типа boolean. В реализации виртуальной машины Java компании Oracle массивы значений типа boolean (тип T_BOOLEAN (см. §2.2)), представлены как массивы, хранящие 8 бит информации на одно значение типа boolean. Другие реализации могут использовать упакованные массивы для хранения boolean; инструкция baload также должна использоваться и для доступа к таким массивам. |
bastore | bastore |
Операция | Загружает значение типа byte или boolean в массив из стека |
Формат |
|
Формы | bastore= 84 (0x54) |
Стек операндов | ..., ссылка на массив, индекс, значение→
... |
Описание | Ссылка на массив должна принадлежать типу reference и ссылаться на массив, чьи компоненты являются типами byte или boolean. Индекс должен принадлежать типу int. Как ссылка на массив, индекс так и значение считываются из стека операндов. Значение, принадлежащее типу int, урезается до типа byte и записывается в массив, в элемент с заданным индексом. |
Исключения времени выполнения | Если ссылка на массив равна null, bastore генерирует NullPointerException.
Если индекс вне границ массива, то bastore генерирует ArrayIndexOutOfBoundsException. |
Примечания | Инструкция bastore используется для записи в массив значений как типа byte так и типа boolean. В реализации виртуальной машины компании Oracle массивы значений типа boolean (тип T_BOOLEAN (см. §2.2)), представлены как массивы, хранящие 8 бит информации на одно значение типа boolean. Другие реализации могут использовать упакованные массивы для хранения boolean; инструкция bastore также должна использоваться и для записи значений в такие массивы. |
bipush | bipush |
Операция | Записывает значение типа byte в стек |
Формат |
|
Формы | bipush= 16 (0x10) |
Стек операндов | ..., →
..., значение |
Описание | С помощью знакового расширения значение байта преобразуется к типу int и записывается в стек операндов. |
caload | caload |
Операция | Загружает значение типа char из массива в стек |
Формат |
|
Формы | caload= 52 (0x34) |
Стек операндов | ..., ссылка на массив, индекс →
..., значение |
Описание | Ссылка на массив должна принадлежать типу reference и ссылаться на массив, чьи компоненты являются типами char. Индекс должен принадлежать типу int. Как ссылка на массив, так и индекс считываются из стека операндов. Значение считывается из элемента массива с заданным индексом, расширяется без учёта знака до типа int и записывается вершину стека операндов. |
Исключения времени выполнения | Если ссылка на массив равна null, то caload генерирует NullPointerException.
Если индекс вне границ массива, то caload генерирует ArrayIndexOutOfBoundsException. |
castore | castore |
Операция | Загружает значение типа char в массив |
Формат |
|
Формы | castore= 85 (0x55) |
Стек операндов | ..., ссылка на массив, индекс, значение →
... |
Описание | Ссылка на массив должна принадлежать типу reference и ссылаться на массив, чьи компоненты являются типами char. Индекс должен принадлежать типу int. Как ссылка на массив, индекс так и значение считываются из стека операндов. Значение, принадлежащее типу char, урезается до типа byte и записывается в массив, в элемент с заданным индексом. |
Исключения времени выполнения | Если ссылка на массив равна null, castore генерирует NullPointerException.
Если индекс вне границ массива, то castore генерирует ArrayIndexOutOfBoundsException. |
checkcast | checkcast |
Операция | Проверяет, принадлежит ли объект заданному типу |
Формат |
|
Формы | checkcast= 192 (0xc0) |
Стек операндов | ..., ссылка на объект →
..., ссылка на объект |
Описание | Ссылка на объект должна принадлежать типу reference. Беззнаковые байт_индекса1 и байт_индекса2 используются для построения индекса массива в константном пуле времени выполнения текущего класса (см. §2.6). Значение индекса определяется как (байт_индекса1 << 8)|(байт_индекса2). Элемент константного пула, на который указывает построенный индекс, должен быть ссылкой на класс, массив или интерфейс.
Если ссылка на объект равна null, то содержимое стека операндов не меняется. В противном случае класс, массив или интерфейс разрешается (см. §5.4.3.1). Если ссылка на объект может быть преобразована к разрешённому ранее классу, массиву или интерфейсу, то стек операндов не меняется. В противном случае инструкция checkcast генерирует исключение ClassCastException. Если ссылка на объект не равна null, то используются следующие правила для разрешения типов: если S - класс, на который ссылается ссылка на объект, а T – разрешаемый класс, массив или интерфейс, то checkcast проверяет следующее:
|
Исключения связывания | Во время разрешения символьной ссылки на класс, массив или интерфейс, может быть создано любое исключение, описанное в (§5.4.3.1). |
Исключения времени выполнения | Если ссылка на объект не может быть преобразована к разрешённому классу, массиву или интерфейсу checkcast генерирует ClassCastException. |
Примечания | Инструкция checkcast очень похожа на инструкцию instanceof. Они отличаются друг от друга реакцией на null (checkcast генерирует исключение, instanceof записывает код результата в стек) и влиянием на стек операндов. |
d2f | d2f |
Операция | Преобразует double к float |
Формат |
|
Формы | d2f= 144 (0x90) |
Стек операндов | ..., значение →
..., результат |
Описание | Значение на вершине стека операндов должно быть типа double. Оно считывается из стека операндов и подвергается набору преобразований (см. §2.8.3). Затем новое значение преобразуется к типу float согласно стандарту IEEE 754. Результат записывается в стек операндов.
Там, где инструкция d2f работает в режиме FP-strict (см. §2.8.2) результат преобразования всегда округляется к ближайшему представимому значению во множестве значений типа float (см. §2.3.2) Там, где инструкция d2f работает в не режиме FP-strict, результат преобразования может быть взят расширенного набора значений с плавающей точкой (§2.3.2); оно не обязательно округляется к ближайшему представимому значению во множестве значений типа float. Если новое значение слишком мало, чтоб быть представленным как float, оно преобразуется к нулю типа float того же знака. Если новое значение слишком велико, чтоб быть представленным как float, оно преобразуется к бесконечности типа float того же знака. Не-число (NaN) типа double преобразуется в не-число типа float. |
Примечания | Инструкция d2f выполняет сужающее преобразование примитивных типов, поэтому может преобразуемая величина быть потеряна полностью либо потеряна точность представления. |
d2i | d2i |
Операция | Преобразует double к int |
Формат |
|
Формы | d2i= 142 (0x8e) |
Стек операндов | ..., значение →
..., результат |
Описание | Значение на вершине стека операндов должно быть типа double. Оно считывается из стека операндов и подвергается набору преобразований (см. §2.8.3). Затем новое значение преобразуется к типу int. Результат записывается в стек операндов.
|
Примечания | Инструкция d2i выполняет сужающее преобразование примитивных типов, поэтому может преобразуемая величина быть потеряна полностью либо потеряна точность представления. |
d2l | d2l |
Операция | Преобразует double к long |
Формат |
|
Формы | d2l= 143 (0x8f) |
Стек операндов | ..., значение →
..., результат |
Описание | Значение на вершине стека операндов должно быть типа double. Оно считывается из стека операндов и подвергается набору преобразований (см. §2.8.3). Затем новое значение преобразуется к типу long. Результат записывается в стек операндов.
|
Примечания | Инструкция d2l выполняет сужающее преобразование примитивных типов, поэтому может преобразуемая величина быть потеряна полностью либо потеряна точность представления. |
dadd | dadd |
Операция | Складывает два числа типа double |
Формат |
|
Формы | dadd= 99 (0x63) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу double. Значения считываются из стека операндов, проходят преобразования (см. §2.8.3) становясь значением1` и значением2`. Результат типа double равен сумме значение1` + значение2`. Результат записывается в стек операндов.
Суммирование производится согласно правилам арифметики IEEE: Если либо значение1` либо значение2` есть не-число NaN, то результат есть NaN.
Инструкция dadd не генерирует исключение, если происходит переполнение или потеря точности. |
daload | daload |
Операция | Загружает значение типа double из массива в стек |
Формат |
|
Формы | daload= 49 (0x31) |
Стек операндов | ..., ссылка на массив, индекс →
..., значение |
Описание | Ссылка на массив должна быть типа reference и ссылаться на массив, чьи компоненты значения типа double. Индекс должен принадлежать типу int. Как ссылка на массив, так и индекс считываются из стека операндов. Значение типа double считывается из элемента массива с соответствующим индексом и записывается в стек операндов. |
Исключения времени выполнения | Если ссылка на массив равна null, то daload генерирует NullPointerException. В противном случае, если индекс вне границ массива, генерируется исключение ArrayIndexOutOfBoundsException. |
dastore | dastore |
Операция | Загружает значение типа double в массив |
Формат |
|
Формы | dastore= 82 (0x52) |
Стек операндов | ..., ссылка на массив, индекс, значение →
... |
Описание | Ссылка на массив должна быть типа reference и ссылаться на массив, чьи компоненты значения типа double. Индекс должен принадлежать типу int, значение должно принадлежать типу double. Ссылка на массив, индекс и значение считываются из стека операндов. Над значением проводится набор преобразований (см. §2.8.3), в результате которых значение` сохраняется в массиве с заданным индексом. |
Исключения времени выполнения | Если ссылка на массив равна null, то dastore генерирует NullPointerException. В противном случае, если индекс вне границ массива, генерируется исключение ArrayIndexOutOfBoundsException. |
dcmp<op> | dcmp<op> |
Операция | Сравнивает два значения типа double |
Формат |
|
Формы | dcmpg= 152 (0x98)
dcmpl= 151 (0x97) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу double. Значения считываются из стека операндов и подвергаются набору преобразований (см. §2.8.3) и заменяются на значение1` и значение2`. Сравнение значений с плавающей точкой производится следующим образом:
Сравнение чисел с плавающей точкой выполняется согласно требованиям стандарта IEEE754. Все значения, отличные от не-числа NaN упорядочены, причём отрицательная бесконечность меньше чем все числа, а положительная бесконечность больше чем все числа. Положительный и отрицательный ноль считаются равными. |
Примечания | Инструкции dcmpg и dcmpl отличаются только своим поведением при сравнении не-чисел NaN. Поскольку NaN не упорядочено, любое сравнения не-числа NaN и значения типа double не определено, в случае, когда один либо оба операнда не-числа NaN. С помощью инструкций dcmpg и dcmpl любое сравнения чисел типа double может быть скомпилировано так, чтобы выдавать результат, совпадающий и при сравнение обычных чисел и при сравнении не-чисел NaN. Более подробную информацию см. в §3.5. |
dconst_<d> | dconst_<d> |
Операция | Записывает константу типа double в стек |
Формат |
|
Формы | dconst_0= 14 (0xe)
dconst_1= 15 (0xf) |
Стек операндов | ...→
... <d> |
Описание | Записывает в стек операндов константу <d> (0.0 или 1.0) типа double. |
ddiv | ddiv |
Операция | Делит два значения типа double |
Формат |
|
Формы | ddiv= 111 (0x6f) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу double. Значения считываются из стека операндов и подвергаются набору преобразований (см. §2.8.3) и заменяются на значение1` и значение2`. Результат – это число типа double равное значение1`/ значение2`. Затем результат записывается в стек операндов.
Результат инструкции ddiv вычисляется согласно правилам арифметики стандарта IEEE:
Несмотря на переполнение, потерю точности, деление на ноль инструкция ddiv никогда не генерирует исключение времени выполнения. |
dload | dload |
Операция | Загружает значение типа double из локальной переменной в стек |
Формат |
|
Формы | dload= 24 (0x18) |
Стек операндов | ...→
..., значение |
Описание | Индекс является беззнаковым байтом. Индекс и величина индекс+1 должны принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Локальная переменная с заданным индексом должна содержать величину типа double. Значение локальной переменной, с заданным индексом, записывается в стек операндов. |
Примечания | Инструкция dload может быть использована совместно с инструкцией wide, когда необходимо задать двухбайтовый беззнаковый индекс локальной переменной. |
dload_<n> | dload_<n> |
Операция | Загружает значение типа double из локальной переменной в стек |
Формат |
|
Формы | dload_0= 38 (0x26)
dload_1= 39 (0x27) dload_2= 40 (0x28) dload_3= 41 (0x29) |
Стек операндов | ... →
..., значение |
Описание | И <n> и величина <n>+1 должны принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Локальная переменная с индексом <n> должна содержать величину типа double. Значение локальной переменной с индексом <n>, записывается в стек операндов. |
Примечания | Каждая из инструкции dload_<n> выполняет то же, что и dload с явным индексом <n> за исключением того, что операнд <n> задан не явно. |
dmul | dmul |
Операция | Умножает два значения типа double |
Формат |
|
Формы | dmul= 107 (0x6b) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу double. Значения считываются из стека операндов и подвергаются набору преобразований (см. §2.8.3) и заменяются на значение1` и значение2`. Результат – это число типа double равное значение1`* значение2`. Затем результат записывается в стек операндов.
Результат инструкции dmul вычисляется согласно правилам арифметики стандарта IEEE:
Несмотря на переполнение, потерю точности dmul никогда не генерирует исключение времени выполнения. |
dneg | dneg |
Операция | Инвертирует значение типа double |
Формат |
|
Формы | dneg= 119 (0x77) |
Стек операндов | ..., значение →
..., результат |
Описание | Значение должно принадлежать типу double. Оно считывается из стека операндов, и подвергаются набору преобразований (см. §2.8.3), а затем заменяется значением`. Результат – это число типа double равное арифметическому отрицанию значения`. Затем результат записывается в стек операндов.
Для значений типа double отрицание не есть то же самое, что и вычитание из нуля. Если x это +0.0, то 0.0 - x равно +0.0, но -x равно -0.0. Унарный минус лишь инвертирует знак числа типа double. Особые случаи:
|
drem | drem |
Операция | Остаток от деления двух чисел типа double |
Формат |
|
Формы | drem= 115 (0x73) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу double. Значения считываются из стека операндов и подвергаются набору преобразований (см. §2.8.3) и заменяются значением1` и значением2`. Результат вычисляется и записывается в стек операндов с типом double.
Результат инструкции drem не совпадает с операцией вычисления остатка для чисел с плавающей точкой, определённой в стандарте IEEE 754. Операция вычисления остатка, заданная в стандарте IEEE 754, вычисляет остаток от «округляющего» деления, а не «урезающего» деления, так что её поведение не аналогично обычной операции целочисленного вычисления остатка. Вместо этого в виртуальной машине Java поведение инструкции drem определено наподобие инструкций целочисленного вычисления остатка (irem и lrem); инструкцию drem можно сравнить с библиотечной функцией fmod языка C. Результат инструкции drem вычисляется согласно следующим правилам:
Несмотря на деление на ноль инструкция drem никогда не генерирует исключение времени выполнения. Переполнение и потеря точности не могут произойти для этой инструкции. |
Примечания | Остаток от деления согласно спецификации IEEE 754 может быть вычислен с помощью метода Math.IEEEremainder. |
dreturn | dreturn |
Операция | Возвращает значение типа double из метода |
Формат |
|
Формы | dreturn= 175 (0xaf) |
Стек операндов | ..., значение →
[пусто] |
Описание | Текущий метод должен возвращать величину типа double. Значение также должно принадлежать double. Если текущий метод объявлен с ключевым словом synchronized, то при входе в метод монитор захватывается первоначально (либо повторно, если уже был захвачен до того), а при выходе освобождается, как при выполнении инструкции monitorexit для текущего потока. Если в ходе выполнения метода не было исключений, значение считывается из стека операндов текущего фрейма (см. §2.6) и проходит ряд преобразований (см. §2.8.3). Затем преобразованное значение` записывается в стек операндов фрейма, принадлежащего вызывающему методу. Все остальные значения стека операндов текущего фрейма теряются.
Затем интерпретатор передаёт управление вызывающему методу, делая текущим соответствующий фрейм. |
Исключения времени выполнения | Если реализация виртуальной машины Java не поддерживает правила структурных блокировок описанные в §2.11.10, тогда если текущий метод объявлен как synchronized и текущий поток не является владельцем монитора, захваченного при входе в метод, то при вызове dreturn будет выброшено исключение IllegalMonitorStateException. Это может произойти, если synchronized-метод содержит инструкцию monitorexit, а инструкция monitorenter по объекту синхронизации отсутствует.
С другой стороны, если реализация виртуальной машины Java поддерживает правила структурных блокировок описанные в §2.11.10, и во время выполнения текущего метода нарушено первое из этих правил, то при вызове dreturn будет выброшено исключение IllegalMonitorStateException. |
dstore | dstore |
Операция | Считывает значение типа double из стека и сохраняет в локальной переменной |
Формат |
|
Формы | dstore= 57 (0x39) |
Стек операндов | ..., значение →
... |
Описание | Индекс является беззнаковым байтом. Индекс и величина индекс+1 должны принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Значение на вершине стека операндов должно принадлежать типу double. Оно считывается из стека операндов, и подвергаются набору преобразований (см. §2.8.3), а затем заменяется значением`. В локальные переменные с индексами индекс и индекс+1 записывается значение`. |
Примечания | Инструкция dstore может быть использована совместно с инструкцией wide, когда необходимо задать двухбайтовый беззнаковый индекс локальной переменной. |
dstore_<n> | dstore_<n> |
Операция | Считывает значение типа double из стека и сохраняет в локальной переменной |
Формат |
|
Формы | dstore_0= 71 (0x47)
dstore_1= 72 (0x48) dstore_2= 73 (0x49) dstore_3= 74 (0x4a) |
Стек операндов | ..., значение →
... |
Описание | И <n> и величина <n>+1 должны принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Значение на вершине стека операндов должно принадлежать типу double. Оно считывается из стека операндов, и подвергаются набору преобразований (см. §2.8.3), а затем заменяется значением`. В локальные переменные с индексами <n> и <n> +1 записывается значение`. |
Примечания | Каждая из инструкции dstore_<n> выполняет то же, что и dstore с явным индексом <n> за исключением того, что операнд <n> задан не явно. |
dsub | dsub |
Операция | Вычитает два значения типа double |
Формат |
|
Формы | dsub= 103 (0x67) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу double. Значения считываются из стека операндов и подвергаются набору преобразований (см. §2.8.3) и заменяются на значение1` и значение2`. Результат – это число типа double равное значение1`- значение2`. Затем результат записывается в стек операндов.
Для операндов типа double всегда справедливо, что выражение a-b даёт такой же результат, как и a+(-b). Тем не менее, для инструкции dsub вычитание значения из нуля не то же самое, что и отрицание, потому что если x это +0.0, тогда 0.0-x равно +0.0, но -x равно -0.0. Несмотря на переполнение, потерю точности dsub никогда не генерирует исключение времени выполнения. |
dup | dup |
Операция | Дублирует значение на вершине стека операндов |
Формат |
|
Формы | dup= 89 (0x59) |
Стек операндов | ..., значение →
..., значение, значение |
Описание | Копирует значение на вершине стека операндов и записывает копию на вершину стека.
Инструкция dup не должна использоваться, если значение не принадлежит категории 1 вычислимых типов (см. §2.11.1) |
dup_x1 | dup_x1 |
Операция | Дублирует значение на вершине стека операндов и записывает его двумя значениями ниже в стек |
Формат |
|
Формы | dup_x1= 90 (0x5a) |
Стек операндов | ..., значение2, значение1 →
..., значение1, значение2, значение1 |
Описание | Копирует значение на вершине стека операндов и записывает копию двумя значениями ниже в стек.
Инструкция dup_x1 не должна использоваться, если значение1 и значение2 не принадлежат категории 1 вычислимых типов (см. §2.11.1) |
dup_x2 | dup_x2 |
Операция | Дублирует значение на вершине стека операндов и записывает его двумя или тремя значениями ниже в стек |
Формат |
|
Формы | dup_x2= 91 (0x5b) |
Стек операндов | Форма 1:
..., значение3, значение2, значение1 → ..., значение1, значение3, значение2, значение1 где значение1, значение2 и значение3 принадлежат категории 1 вычислимых типов (см. §2.11.1)
Форма 2: ..., значение2, значение1 → ..., значение1, значение2, значение1 где значение1 принадлежит категории 1 вычислимых типов, а значение2 принадлежит категории 2 (см. §2.11.1) |
Описание | Копирует значение на вершине стека операндов и записывает копию двумя или тремя значениями ниже в стек. |
dup2 | dup2 |
Операция | Дублирует один или два операнда на вершине стека |
Формат |
|
Формы | dup2= 92 (0x5c) |
Стек операндов | Форма 1:
..., значение2, значение1, значение2, значение1 где значение1, значение2 принадлежат категории 1 вычислимых типов (см. §2.11.1)
Форма 2:
..., значение, значение где значение принадлежит категории 2 вычислимых типов (см. §2.11.1) |
Описание | Копирует одно или два значения на вершине стека операндов и записывает копию (одно или два значения) в стек. |
dup2_x1 | dup2_x1 |
Операция | Дублирует один или два операнда на вершине стека и записывает его двумя или тремя значениями ниже в стек |
Формат |
|
Формы | dup2_x1= 93 (0x5d) |
Стек операндов | Форма 1:
..., значение3, значение2, значение1 → ..., значение2, значение1, значение3, значение2, значение1 где значение1, значение2 и значение3 принадлежат категории 1 вычислимых типов (см. §2.11.1)
Форма 2:
..., значение2, значение1 → ..., значение1, значение2, значение1 где значение1 принадлежит категории 2 вычислимых типов, а значение2 принадлежит категории 1 (см. §2.11.1) |
Описание | Копирует одно или два значения на вершине стека операндов и записывает копию (одно или два значения) в стек ниже на одно или два значения. |
dup2_x2 | dup2_x2 |
Операция | Дублирует один или два операнда на вершине стека и записывает его двумя, тремя или четырьмя значениями ниже в стек |
Формат |
|
Формы | dup2_x2= 94 (0x5e) |
Стек операндов | Форма 1:
..., значение2, значение1, значение4, значение3, значение2, значение1 где значение1, значение2, значение3 и значение4 принадлежат категории 1 вычислимых типов (см. §2.11.1)
Форма 2:
..., значение1, значение3, значение2, значение1 где значение1 принадлежит категории 2 вычислимых типов, а значение2 и значение3 принадлежат категории 1 (см. §2.11.1)
Форма 3:
..., значение2, значение1, значение3, значение2, значение1 где значение1 и значение2 принадлежат категории 1 вычислимых типов, а значение3 принадлежит категории 1 (см. §2.11.1)
Форма 4:
..., значение1, значение2, значение1 где значение1 и значение3 принадлежат категории 2 вычислимых типов (см. §2.11.1) |
Описание | Копирует одно или два значения на вершине стека операндов и записывает копию (одно или два значения) в стек. |
f2d | f2d |
Операция | Преобразует значение типа float к double |
Формат |
|
Формы | f2d= 141 (0x8d) |
Стек операндов | ..., значение→
..., результат |
Описание | Значение на вершине стека операндов должно быть типа float. Оно считывается из стека операндов и подвергается набору преобразований (см. §2.8.3). Затем новое значение преобразуется к типу double. Результат записывается в стек операндов. |
Примечания | Там, где инструкция f2d работает в режиме FP-strict (см. §2.8.2), будет выполнено расширение примитивных типов (см. JLS §5.1.2). Поскольку все значения множества чисел с плавающей точкой одинарной точности (см. §2.3.2) однозначно представимы значениями двойной точности, то расширение будет выполнено без потери точности.
Там, где инструкция f2d работает не в режиме FP-strict, результат преобразования может быть взят из множества значений двойной точности с расширенной экспонентой; он не обязательно округляется к ближайшему представимому значению двойной точности. Однако, если значение принадлежит множеству одинарной точности с расширенной экспонентой, а результат необходимо представить как значение двойной точности (но не с расширенной экспонентой), то может потребоваться округление значения. |
f2i | f2i |
Операция | Преобразует значение типа float к int |
Формат |
|
Формы | f2i= 139 (0x8b) |
Стек операндов | ..., значение →
..., результат |
Описание | Значение на вершине стека операндов должно быть типа float. Оно считывается из стека операндов и подвергается набору преобразований (см. §2.8.3). Затем новое значение преобразуется к типу int. Результат записывается в стек операндов.
|
Примечания | Инструкция f2i выполняет сужающее преобразование примитивных типов, поэтому преобразуемая величина может быть потеряна полностью либо потеряна точность представления. |
f2l | f2l |
Операция | Преобразует значение типа float к long |
Формат |
|
Формы | f2l= 140 (0x8c) |
Стек операндов | ..., значение →
..., результат |
Описание | Значение на вершине стека операндов должно быть типа float. Оно считывается из стека операндов и подвергается набору преобразований (см. §2.8.3). Затем новое значение преобразуется к типу long. Результат записывается в стек операндов.
|
Примечания | Инструкция f2l выполняет сужающее преобразование примитивных типов, поэтому преобразуемая величина может быть потеряна полностью либо потеряна точность представления. |
fadd | fadd |
Операция | Складывает два значения типа float |
Формат |
|
Формы | fadd= 98 (0x62) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу float. Значения считываются из стека операндов, проходят преобразования (см. §2.8.3) становясь значением1` и значением2`. Результат типа float равен сумме значение1` + значение2`. Результат записывается в стек операндов.
Суммирование производится согласно правилам арифметики IEEE:
Инструкция fadd не генерирует исключение, если происходит переполнение или потеря точности. |
faload | faload |
Операция | Записывает в стек значение из массива типа float |
Формат |
|
Формы | faload= 48 (0x30) |
Стек операндов | ..., ссылка на массив, индекс →
..., значение |
Описание | Ссылка на массив должна быть типа reference и ссылаться на массив, чьи компоненты значения типа float. Индекс должен принадлежать типу int. Как ссылка на массив, так и индекс считываются из стека операндов. Значение типа float считывается из элемента массива с соответствующим индексом и записывается в стек операндов. |
Исключения времени выполнения | Если ссылка на массив равна null, то faload генерирует NullPointerException. В противном случае, если индекс вне границ массива, генерируется исключение ArrayIndexOutOfBoundsException. |
fastore | fastore |
Операция | Записывает значение типа float в массив |
Формат |
|
Формы | fastore= 81 (0x51) |
Стек операндов | ..., ссылка на массив, индекс, значение →
... |
Описание | Ссылка на массив должна быть типа reference и ссылаться на массив, чьи компоненты значения типа float. Индекс должен принадлежать типу int, значение должно принадлежать типу float. Ссылка на массив, индекс и значение считываются из стека операндов. Над значением проводится набор преобразований (см. §2.8.3), в результате которых значение` сохраняется в массиве с заданным индексом. |
Исключения времени выполнения | Если ссылка на массив равна null, то fastore генерирует NullPointerException. В противном случае, если индекс вне границ массива, генерируется исключение ArrayIndexOutOfBoundsException. |
fcmp<op> | fcmp<op> |
Операция | Сравнивает два значение типа float |
Формат |
|
Формы | fcmpg= 150 (0x96)
fcmpl= 149 (0x95) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу float. Значения считываются из стека операндов и подвергаются набору преобразований (см. §2.8.3) и заменяются на значение1` и значение2`.
Сравнение значений с плавающей точкой производится следующим образом:
Сравнение чисел с плавающей точкой выполняется согласно требованиям стандарта IEEE754. Все значения, отличные от не-числа NaN упорядочены, причем отрицательная бесконечность меньше чем все числа, а положительная бесконечность больше чем все числа. Положительный и отрицательный ноль считаются равными. |
Примечания | Инструкции fcmpg и fcmpl отличаются только своим поведением при сравнении не-чисел NaN. Поскольку NaN не упорядочено, любое сравнения не-числа NaN и значения типа float не определено, в случае, когда один либо оба операнда не-числа NaN. С помощью инструкций fcmpg и fcmpl любое сравнения чисел типа float может быть скомпилировано так, чтобы выдавать результат, совпадающий и при сравнение обычных чисел и при сравнении не-чисел NaN. Более подробную информацию см. в §3.5. |
fconst_<f> | fconst_<f> |
Операция | Записывает в стек константу типа float |
Формат |
|
Формы | fconst_0= 11 (0xb)
fconst_1= 12 (0xc) fconst_2= 13 (0xd) |
Стек операндов | ... →
..., <f> |
Описание | Записывает константу <f> типа float (0.0, 1.0 или 2.0) в стек операндов. |
fdiv | fdiv |
Операция | Делит два значение типа float |
Формат |
|
Формы | fdiv= 110 (0x6e) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу float. Значения считываются из стека операндов и подвергаются набору преобразований (см. §2.8.3) и заменяются на значение1` и значение2`.
Результат – это число типа float равное значение1`/ значение2`. Затем результат записывается в стек операндов. Результат инструкции fdiv вычисляется согласно правилам арифметики стандарта IEEE:
Несмотря на переполнение, потерю точности, деление на ноль инструкция fdiv никогда не генерирует исключение времени выполнения. |
fload | fload |
Операция | Записывает в стек значение типа float из локальной переменной |
Формат |
|
Формы | fload= 23 (0x17) |
Стек операндов | ...→
..., значение |
Описание | Индекс является беззнаковым байтом. Индекс должен принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Локальная переменная с заданным индексом должна содержать величину типа float. Значение локальной переменной, с заданным индексом, записывается в стек операндов. |
Примечания | Инструкция fload может быть использована совместно с инструкцией wide, когда необходимо задать двухбайтовый беззнаковый индекс локальной переменной. |
fload_<n> | fload_<n> |
Операция | Записывает в стек значение типа float из локальной переменной |
Формат |
|
Формы | 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 | fmul |
Операция | Умножает два значения типа float |
Формат |
|
Формы | fmul= 106 (0x6a) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу float. Значения считываются из стека операндов и подвергаются набору преобразований (см. §2.8.3) и заменяются на значение1` и значение2`.
Результат – это число типа float равное значение1`* значение2`. Затем результат записывается в стек операндов. Результат инструкции fmul вычисляется согласно правилам арифметики стандарта IEEE:
Несмотря на переполнение, потерю точности fmul никогда не генерирует исключение времени выполнения. |
fneg | fneg |
Операция | Инвертирует значение типа float |
Формат |
|
Формы | fneg= 118 (0x76) |
Стек операндов | ..., значение →
..., результат |
Описание | Значение должно принадлежать типу float. Оно считывается из стека операндов, и подвергаются набору преобразований (см. §2.8.3), а затем заменяется значением`. Результат – это число типа float равное арифметическому отрицанию значения`. Затем результат записывается в стек операндов.
Для значений типа float отрицание не есть то же самое, что и вычитание из нуля. Если x это +0.0, то 0.0 - x равно +0.0, но -x равно -0.0. Унарный минус лишь инвертирует знак числа типа float. Особые случаи:
|
frem | frem |
Операция | Остаток от деления двух значений типа float |
Формат |
|
Формы | frem= 114 (0x72) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу float. Значения считываются из стека операндов и подвергаются набору преобразований (см. §2.8.3) и заменяются значением1` и значением2`.
Результат вычисляется и записывается в стек операндов с типом float. Результат инструкции frem не совпадает с операцией вычисления остатка для чисел с плавающей точкой, определённой в стандарте IEEE 754. Операция вычисления остатка, заданная в стандарте IEEE 754, вычисляет остаток от «округляющего» деления, а не «урезающего» деления, так что ее поведение не аналогично обычной операции целочисленного вычисления остатка. Вместо этого в виртуальной машине Java поведение инструкции frem определено наподобие инструкций целочисленного вычисления остатка (irem и lrem); инструкцию frem можно сравнить с библиотечной функцией fmod языка C. Результат инструкции frem вычисляется согласно следующим правилам:
Несмотря на деление на ноль инструкция frem никогда не генерирует исключение времени выполнения. Переполнение и потеря точности не могут произойти для этой инструкции. |
Примечания | Остаток от деления согласно спецификации IEEE 754 может быть вычислен с помощью метода Math.IEEEremainder. |
freturn | freturn |
Операция | Возвращает значение float из метода |
Формат |
|
Формы | freturn= 174 (0xae) |
Стек операндов | ..., значение →
[пусто] |
Описание | Текущий метод должен возвращать величину типа float. Значение также должно принадлежать float. Если текущий метод объявлен с ключевым словом synchronized, то при входе в метод монитор захватывается первоначально (либо повторно, если уже был захвачен до того), а при выходе освобождается, как при выполнении инструкции monitorexit для текущего потока. Если в ходе выполнения метода не было исключений, значение считывается из стека операндов текущего фрейма (см. §2.6) и проходит ряд преобразований (см. §2.8.3). Затем преобразованное значение` записывается в стек операндов фрейма, принадлежащего вызывающему методу. Все остальные значения стека операндов текущего фрейма теряются.
Затем интерпретатор передаёт управление вызывающему методу, делая текущим соответствующий фрейм. |
Исключения времени выполнения | Если реализация виртуальной машины Java не поддерживает правила структурных блокировок описанные в §2.11.10, тогда если текущий метод объявлен как synchronized и текущий поток не является владельцем монитора, захваченного при входе в метод, то при вызове freturn будет выброшено исключение IllegalMonitorStateException. Это может произойти, если synchronized-метод содержит инструкцию monitorexit, а инструкция monitorenter по объекту синхронизации отсутствует.
С другой стороны, если реализация виртуальной машины Java поддерживает правила структурных блокировок описанные в §2.11.10, и во время выполнения текущего метода нарушено первое из этих правил, то при вызове freturn будет выброшено исключение IllegalMonitorStateException. |
fstore | fstore |
Операция | Загружает значение типа float из стека в локальную переменную |
Формат |
|
Формы | fstore= 56 (0x38) |
Стек операндов | ..., значение →
... |
Описание | Индекс является беззнаковым байтом и должен принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Значение на вершине стека операндов должно принадлежать типу float. Оно считывается из стека операндов, и подвергаются набору преобразований (см. §2.8.3), а затем заменяется значением`. В локальную переменную с индексом индекс записывается значение`. |
Примечания | Инструкция fstore может быть использована совместно с инструкцией wide, когда необходимо задать двухбайтовый беззнаковый индекс локальной переменной. |
fstore_<n> | fstore_<n> |
Операция | Загружает значение типа float из стека в локальную переменную |
Формат |
|
Формы | fstore_0= 67 (0x43)
fstore_1= 68 (0x44) fstore_2= 69 (0x45) fstore_3= 70 (0x46) |
Стек операндов | ..., значение →
... |
Описание | <n> должно принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Значение на вершине стека операндов должно принадлежать типу float. Оно считывается из стека операндов, и подвергаются набору преобразований (см. §2.8.3), а затем заменяется значением`. В локальную переменную с индексом <n> записывается значение`. |
Примечания | Каждая из инструкции fstore_<n> выполняет то же, что и fstore с явным индексом <n> за исключением того, что операнд <n> задан не явно. |
fsub | fsub |
Операция | Вычитает два значения типа float |
Формат |
|
Формы | fsub= 102 (0x66) |
Стек операндов | ..., значение1, значение2 →
...,результат |
Описание | И значение1 и значение2 должны принадлежать типу float. Значения считываются из стека операндов и подвергаются набору преобразований (см. §2.8.3) и заменяются на значение1` и значение2`. Результат – это число типа float равное значение1`- значение2`. Затем результат записывается в стек операндов.
Для операндов типа float всегда справедливо, что выражение a-b дает такой же результат, как и a+(-b). Тем не менее, для инструкции fsub вычитание значения из нуля не то же самое, что и отрицание, потому что если x это +0.0, тогда 0.0-x равно +0.0, но -x равно -0.0. Несмотря на переполнение, потерю точности fsub никогда не генерирует исключение времени выполнения. |
getfield | getfield |
Операция | Извлекает поле из объекта |
Формат |
|
Формы | getfield= 180 (0xb4) |
Стек операндов | ..., ссылка на объект →
..., значение |
Описание | Ссылка на объект, которая должна принадлежать типу reference, считывается из стека операндов. Беззнаковые байт_индекса1 и байт_индекса2 используются для построения индекса элемента в константном пуле времени выполнения текущего класса (см. §2.6). Значение индекса рассчитывается по формуле (байт_индекса1 << 8) | байт_индекса2. Элемент константного пула с рассчитанным индексом должен быть ссылкой на поле (см. §5.1). Эта ссылка на поле содержит имя поля и его дескриптор, а также ссылку на класс, где это поле может быть найдено. Затем по ссылке на объект и дескриптору поля значение считывается и записывается в стек операндов.
Ссылка на объект не должна ссылаться на массив. Если поле класса объявлено как protected (см. §4.6) и оно принадлежит предку текущего класса и не объявлено в том же пакете что и текущий класс (§5.3), то в этом случае ссылка на объект должна указывать либо на текущий класс, либо на его предка. |
Исключения связывания | Во время разрешения ссылки может быть выброшено любое исключение, указанное в §5.4.3.2.
При попытке получить значение поля static с помощью инструкции getfield, будет выброшено исключение IncompatibleClassChangeError. |
Исключения времени выполнения | Если ссылка на объект равна null, инструкция getfield генерирует NullPointerException. |
Примечания | Инструкция getfield не может быть использована для доступа к полю массива length. Для этой цели необходимо использовать инструкцию arraylength. |
getstatic | getstatic |
Операция | Извлекает статическое поле из класса |
Формат |
|
Формы | getstatic= 178 (0xb2) |
Стек операндов | ..., →
..., значение |
Описание | Беззнаковые байт_индекса1 и байт_индекса2 используются для построения индекса элемента в константном пуле времени выполнения текущего класса (см. §2.6). Значение индекса рассчитывается по формуле (байт_индекса1 << 8) | байт_индекса2. Элемент константного пула с рассчитанным индексом должен быть ссылкой на поле (см. §5.1). Эта ссылка на поле содержит имя поля и его дескриптор, а также ссылку на класс или интерфейс, где это поле может быть найдено. После ссылка разрешается (см. §5.4.3.2).
Если разрешение ссылки было успешным, а класс или интерфейс, чьё поле нужно получить, ещё не инициализирован, то класс или интерфейс инициализируется. Затем значение считывается из класса или интерфейса и записывается в стек операндов. |
Исключения связывания | Во время разрешения ссылки может быть выброшено любое исключение, указанное в §5.4.3.2.
При попытке получить значение поля, которое не объявлено статическим, с помощью инструкции getstatic, будет выброшено исключение IncompatibleClassChangeError. |
Исключения времени выполнения | Если вызов инструкции getstatic приводит к инициализации класса или интерфейса, то getstatic может вызвать ошибку, более подробно описанную в разделе §5.5. |
goto | goto |
Операция | Безусловный переход |
Формат |
|
Формы | goto= 167 (0xa7) |
Стек операндов | Без изменений |
Описание | Беззнаковые байт_адреса1 и байт_адреса2 используются для построения 16-битового знакового смещения перехода (байт_адреса1 << 8) | байт_адреса2. Смещение выполняется относительно индекса инструкции goto, управление передаётся команде, находящейся по рассчитанному смещению. Смещение должно находиться в пределах метода, содержащего инструкцию goto. |
goto_w | goto_w |
Операция | Безусловный переход (широкий индекс) |
Формат |
|
Формы | goto_w= 200 (0xc8) |
Стек операндов | Без изменений |
Описание | Беззнаковые байт_адреса1, байт_адреса2, байт_адреса3 и байт_адреса4 используются для построения 32-битового знакового смещения перехода (байт_адреса1 << 24) | (байт_адреса2 << 16) (байт_адреса3 << 8) | байт_адреса4. Смещение выполняется относительно индекса инструкции goto_w, управление передаётся команде, находящейся по рассчитанному смещению. Смещение должно находиться в пределах метода, содержащего инструкцию goto_w. |
Примечания | Хотя инструкция goto_w принимает на вход 4-х байтовое смещение, ограничивающим фактором для перехода является также размер метода, равный 65535 байтам (см. §4.11). Это ограничение может быть снято в последующих версиях виртуальной Java машины. |
i2b | i2b |
Операция | Преобразует значение типа int к byte |
Формат |
|
Формы | i2b= 145 (0x91) |
Стек операндов | ..., значение →
..., результат |
Описание | Значение на вершине стека операндов должно принадлежать типу int. Оно считывается с вершины стека операндов, обрезается до размера byte, а затем расширяется с учётом знака снова к типу int. Результат расширения записывается в стек операндов. |
Примечания | Инструкция i2b выполняет сужающее преобразование примитивных типов (см. JLS §5.1.3). Это может привести к потере исходного значения. Знак результата может также отличатся от знака исходного значения. |
i2c | i2c |
Операция | Преобразует значение типа int к char |
Формат |
|
Формы | i2c= 146 (0x92) |
Стек операндов | ..., значение →
..., результат |
Описание | Значение на вершине стека операндов должно принадлежать типу int. Оно считывается с вершины стека операндов, обрезается до размера char, а затем расширяется без учёта знака снова к типу int. Результат расширения записывается в стек операндов. |
Примечания | Инструкция i2c выполняет сужающее преобразование примитивных типов (см. JLS §5.1.3). Это может привести к потере исходного значения. Знак результата может также отличатся от знака исходного значения. |
i2d | i2d |
Операция | Преобразует значение типа int к double |
Формат |
|
Формы | i2d= 135 (0x87) |
Стек операндов | ..., значение →
..., результат |
Описание | Значение на вершине стека операндов должно принадлежать типу int. Оно считывается с вершины стека операндов и преобразуется к типу double. Результат записывается в стек операндов. |
Примечания | Инструкция i2d выполняет расширяющее преобразование примитивных типов. Поскольку все значения типа int точно представимы в типе double, то преобразование точное. |
i2f | i2f |
Операция | Преобразует значение типа int к float |
Формат |
|
Формы | i2f= 134 (0x86) |
Стек операндов | ..., значение →
..., результат |
Описание | Значение на вершине стека операндов должно принадлежать типу int. Оно считывается с вершины стека операндов и преобразуется к типу double, согласно правилам округления к ближайшему стандарта IEEE 754. Результат записывается в стек операндов. |
Примечания | Инструкция i2d выполняет расширяющее преобразование примитивных типов (см. JLS §5.1.2), но может привести к потере точности, поскольку тип float имеет только 24 бита для хранения мантиссы значения. |
i2l | i2l |
Операция | Преобразует значение типа int к long |
Формат |
|
Формы | i2l= 133 (0x85) |
Стек операндов | ..., значение →
..., результат |
Описание | Значение на вершине стека операндов должно принадлежать типу int. Оно считывается с вершины стека операндов и преобразуется к типу long (путем знакового расширения). Результат записывается в стек операндов. |
Примечания | Инструкция i2l выполняет расширяющее преобразование примитивных типов (см. JLS §5.1.2). Поскольку все значения типа int точно представимы в типе long, то преобразование точное. |
i2s | i2s |
Операция | Преобразует значение типа int к short |
Формат |
|
Формы | i2s= 147 (0x93) |
Стек операндов | ..., значение →
..., результат |
Описание | Значение на вершине стека операндов должно принадлежать типу int. Оно считывается с вершины стека операндов, обрезается до размера short, а затем расширяется с учётом знака снова к типу int. Результат расширения записывается в стек операндов. |
Примечания | Инструкция i2s выполняет сужающее преобразование примитивных типов (см. JLS §5.1.3). Это может привести к потере исходного значения. Знак результата может также отличатся от знака исходного значения. |
iadd | iadd |
Операция | Складывает два значения типа int |
Формат |
|
Формы | iadd= 96 (0x60) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу int. Они считываются с вершины стек операндов. Результат типа int есть значение1 + значение2. Результат записывается в стек операндов.
Результат сложения - это младшие 32 бита результата точного сложения, представленные в двоичном дополнительном коде. Если происходит переполнение, то знак результата может отличаться от знака математической суммы двух значений. Не смотря на то, что при выполнении инструкции iadd может произойти переполнение, инструкция iadd никогда не приводит к исключению времени выполнения. |
iaload | iaload |
Операция | Записывает в стек значение int из массива |
Формат |
|
Формы | iaload= 46 (0x2e) |
Стек операндов | ..., ссылка на массив, индекс →
..., значение |
Описание | Ссылка на массив должна быть типа reference и ссылаться на массив, чьи компоненты значения типа int. Индекс должен принадлежать типу int. Как ссылка на массив, так и индекс считываются из стека операндов. Значение типа int считывается из элемента массива с соответствующим индексом и записывается в стек операндов. |
Исключения времени выполнения | Если ссылка на массив равна null, то iaload генерирует NullPointerException. В противном случае, если индекс вне границ массива, генерируется исключение ArrayIndexOutOfBoundsException. |
iand | iand |
Операция | Логическое «И» над значениями с типом int |
Формат |
|
Формы | iand= 126 (0x7e) |
Стек операндов | ..., значение1, значение2 →
...,результат |
Описание | И значение1 и значение2 должны принадлежать типу int. Они считываются с вершины стек операндов. Результат типа int есть логическое "И" над значением1 и значением2. Результат записывается в стек операндов. |
iastore | iastore |
Операция | Загружает значения типа int из стека в массив |
Формат |
|
Формы | iastore= 79 (0x4f) |
Стек операндов | ..., ссылка на массив, индекс, значение →
... |
Описание | Ссылка на массив должна быть типа reference и ссылаться на массив, чьи компоненты значения типа int. Индекс должен принадлежать типу int, значение должно принадлежать типу int. Ссылка на массив, индекс и значение считываются из стека операндов. Затем значение сохраняется в массиве с заданным индексом. |
Исключения времени выполнения | Если ссылка на массив равна null, то iastore генерирует NullPointerException. В противном случае, если индекс вне границ массива, генерируется исключение ArrayIndexOutOfBoundsException. |
iconst_ | iconst_ |
Операция | Записывает в стек константу типа int |
Формат |
|
Формы | 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) |
Стек операндов | ..., значение →
..., |
Описание | Записывает в стек целочисленную константу (-1, 0, 1, 2, 3, 4 или 5) |
Примечания | Каждая из семейства инструкций эквивалента bipush с соответствующим аргументом, за исключением того, что задано не явно. |
idiv | idiv |
Операция | Делит два целых значения |
Формат |
|
Формы | idiv= 108 (0x6c) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу int. Значения считываются с вершины стека операндов. Результат также принадлежит типу int и равен значение1 / значение2. После вычисления результат записывается в стек операндов.
Результат целочисленного деления округляется по направлению к нулю. Это значит, частное целочисленного деления n / d это число q, максимальное из всех, удовлетворяющих неравенству |d · q| ≤ |n|. Кроме того q положительно, когда |n| ≥ |d| и при этом n и d имеют одинаковый знак и q отрицательно, когда |n| ≥ |d| и при этом n и d имеют разные знаки. Существует один специальный случай, который не подходит под описанные выше правила: если делимое – это отрицательное целое, максимальное по модулю для типа int, а делитель равен -1, то происходит переполнение и результат равен делимому. Несмотря на переполнение, в этом случае исключение не выбрасывается. |
Исключения времени выполнения | Если делитель целочисленного деления есть 0, то idiv генерирует исключение ArithmeticException. |
if_acmp<cond> | if_acmp<cond> |
Операция | Переход, если значения типа reference равны |
Формат |
|
Формы | if_acmpeq= 165 (0xa5)
if_acmpne= 166 (0xa6) |
Стек операндов | ..., значение1, значение2 →
... |
Описание | И значение1 и значение2 должны принадлежать типу reference. Они оба считываются из стека операндов и сравниваются. Результат сравнения следующий:
Если сравнение дало истину, беззнаковые байт_адреса1 и байт_адреса2 используются для построения знакового 16-ти битового смещения, которое вычисляется следующим образом: (байт_адреса1 << 8) | байт_адреса2. Затем выполнение инструкций продолжается со смещения, вычисленного ранее относительно инструкции if_acmp<cond>. Целевой адрес перехода должен быть в пределах метода, содержащего if_acmp<cond>. В противном случае (если сравнение дало ложь), выполнение инструкций продолжается непосредственно с инструкции, следующей за if_acmp<cond>. |
if_icmp<cond> | if_icmp<cond> |
Операция | Переход, если значения типа int удовлетворяют условию |
Формат |
|
Формы | if_icmpeq= 159 (0x9f)
if_icmpne= 160 (0xa0) if_icmplt= 161 (0xa1) if_icmpge= 162 (0xa2) if_icmpgt= 163 (0xa3) if_icmple= 164 (0xa4) |
Стек операндов | ..., значение1, значение2 →
... |
Описание | И значение1 и значение2 должны принадлежать типу int. Они оба считываются из стека операндов и сравниваются. Все сравнения – знаковые. Результаты сравнения вычисляются следующим образом:
Если сравнение дало истину, беззнаковые байт_адреса1 и байт_адреса2 используются для построения знакового 16-ти битового смещения, которое вычисляется следующим образом: (байт_адреса1 << 8) | байт_адреса2. Затем выполнение инструкций продолжается со смещения, вычисленного ранее относительно инструкции if_icmp<cond>. Целевой адрес перехода должен быть в пределах метода, содержащего if_icmp<cond>. В противном случае (если сравнение дало ложь), выполнение инструкций продолжается непосредственно с инструкции, следующей за if_icmp<cond>. |
if<cond> | if<cond> |
Операция | Переход, если сравнение значения типа int с нулем – «истина» |
Формат |
|
Формы | ifeq= 153 (0x99)
ifne= 154 (0x9a) iflt= 155 (0x9b) ifge= 156 (0x9c) ifgt= 157 (0x9d) ifle= 158 (0x9e) |
Стек операндов | ..., значение→
... |
Описание | Значение должно принадлежать типу int. Оно считывается из стека операндов и сравнивается с нулём. Все сравнения – знаковые. Результаты сравнения вычисляются следующим образом:
Если сравнение дало истину, беззнаковые байт_адреса1 и байт_адреса2 используются для построения знакового 16-ти битового смещения, которое вычисляется следующим образом: (байт_адреса1 << 8) | байт_адреса2. Затем выполнение инструкций продолжается со смещения, вычисленного ранее относительно инструкции if<cond>. Целевой адрес перехода должен быть в пределах метода, содержащего if<cond>. В противном случае (если сравнение дало ложь), выполнение инструкций продолжается непосредственно с инструкции, следующей за if<cond>. |
ifnonnull | ifnonnull |
Операция | Переход, если значение типа reference не null |
Формат |
|
Формы | ifnonnull= 199 (0xc7) |
Стек операндов | ..., значение →
... |
Описание | Значение должно принадлежать типу reference. Оно считываются из стека операндов. Если значение не null то, беззнаковые байт_адреса1 и байт_адреса2 используются для построения знакового 16-ти битового смещения, которое вычисляется следующим образом: (байт_адреса1 << 8) | байт_адреса2. Затем выполнение инструкций продолжается со смещения, вычисленного ранее относительно инструкции ifnonnull. Целевой адрес перехода должен быть в пределах метода, содержащего ifnonnull.
В противном случае (если сравнение дало ложь), выполнение инструкций продолжается непосредственно с инструкции, следующей за ifnonnull. |
ifnull | ifnull |
Операция | Переход, если значение типа reference равно null |
Формат |
|
Формы | ifnull= 198 (0xc6) |
Стек операндов | ..., значение→
... |
Описание | Значение должно принадлежать типу reference. Оно считываются из стека операндов. Если значение null то, беззнаковые байт_адреса1 и байт_адреса2 используются для построения знакового 16-ти битового смещения, которое вычисляется следующим образом: (байт_адреса1 << 8) | байт_адреса2. Затем выполнение инструкций продолжается со смещения, вычисленного ранее относительно инструкции ifnull. Целевой адрес перехода должен быть в пределах метода, содержащего ifnull.
В противном случае (если сравнение дало ложь), выполнение инструкций продолжается непосредственно с инструкции, следующей за ifnull. |
iinc | iinc |
Операция | Увеличивает локальную переменную на заданную константу |
Формат |
|
Формы | iinc= 132 (0x84) |
Стек операндов | Без изменений |
Описание | Индекс – это беззнаковый байт, который должен быть индексом локальной переменной текущего фрейма (см. §2.6). Константа – знаковый байт, следующий непосредственно за кодом операции. Локальная переменная с заданным индексом должна содержать значение типа int. Затем константа расширяется с учётом знака до типа int и добавляется к локальной переменной с заданным индексом. |
Примечания | Инструкция iinc может быть использована совместно с инструкцией wide, когда необходимо задать двухбайтовый беззнаковый индекс локальной переменной и при этом увеличить переменную на двухбайтовое знаковое значение. |
iload | iload |
Операция | Загружает значение типа int из локальной переменной в стек |
Формат |
|
Формы | iload= 21 (0x15) |
Стек операндов | ..., →
..., значение |
Описание | Индекс является беззнаковым байтом. Индекс должен принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Локальная переменная с заданным индексом должна содержать величину типа int. Значение локальной переменной, с заданным индексом, записывается в стек операндов. |
Примечания | Инструкция iload может быть использована совместно с инструкцией wide, когда необходимо задать двухбайтовый беззнаковый индекс локальной переменной. |
iload_<n> | iload_<n> |
Операция | Записывает в стек значение локальной переменной типа int |
Формат |
|
Формы | iload_0= 26 (0x1a)
iload_1= 27 (0x1b) iload_2= 28 (0x1c) iload_3= 29 (0x1d) |
Стек операндов | ... →
..., значение |
Описание | <n> должно принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Локальная переменная с заданным <n> должна содержать величину типа int. Значение локальной переменной, с заданным <n>, записывается в стек операндов. |
Примечания | Каждая из инструкции iload_<n> выполняет то же, что и iload с явным индексом <n> за исключением того, что операнд <n> задан не явно. |
imul | imul |
Операция | Умножает два значения типа int |
Формат |
|
Формы | imul= 104 (0x68) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу int. Значения считываются с вершины стека операндов. Результат также принадлежит типу int и равен значение1 * значение2. После вычисления результат записывается в стек операндов.
Результат умножения – это младшие 32 бита истинного математического результата, представленного в двоичном дополнительном формате в типе int. Если происходит переполнение, то знак результата может не совпадать со знаком истинного математического результата. Несмотря на то, что переполнение возможно, исключение инструкцией imul не выбрасывается. |
ineg | ineg |
Операция | Инвертирует значение типа int |
Формат |
|
Формы | ineg= 116 (0x74) |
Стек операндов | ..., значение→
..., результат |
Описание | Значение должно принадлежать типу int. Оно считывается со стека операндов. Результат принадлежит типу int и является арифметическим отрицанием значения. Результат записывается в стек операндов.
Для величин, принадлежащих типу int, отрицание – это тоже, что и вычитание из нуля. Поскольку виртуальная машина Java использует для целых чисел представление в двоичном дополнительном коде, а это представление не симметрично, то отрицание максимального по модулю отрицательного числа типа int есть это же число. В этом случае происходит переполнение, однако, несмотря на это исключение не генерируется. Для всех целых чисел x принадлежащих типу int, -x равно (~x) + 1. |
instanceof | instanceof |
Операция | Определяет, принадлежит ли объект заданному типу |
Формат |
|
Формы | instanceof= 193 (0xc1) |
Стек операндов | ..., ссылка на объект →
..., результат |
Описание | Ссылка на объект должна принадлежать типу reference. Беззнаковые байт_индекса1 и байт_индекса2 используются для построения индекса массива в константном пуле времени выполнения текущего класса (см. §2.6). Значение индекса определяется как (байт_индекса1 << 8)|(байт_индекса2). Элемент константного пула, на который указывает построенный индекс, должен быть ссылкой на класс, массив или интерфейс.
Если ссылка на объект равна null, то в стек операндов записывается результат 0 с типом int. В противном случае класс, массив или интерфейс разрешается (см. §5.4.3.1). Если ссылка на объект может быть преобразована к разрешённому ранее классу, массиву или интерфейсу, то в стек операндов записывается результат 1 с типом int. В противном случае инструкция instanceof в стек операндов записывает результат 0 с типом int.
|
Исключения связывания | Во время разрешения символьной ссылки на класс, массив или интерфейс, может быть создано любое исключение, описанное в (§5.4.3.1). |
Примечания | Инструкция instanceof очень похожа на инструкцию checkcast. Они отличаются друг от друга реакцией на null (checkcast генерирует исключение, instanceof записывает код результата в стек) и влиянием на стек операндов. |
invokedynamic | invokedynamic |
Операция | Динамически вызывает метод |
Формат |
|
Формы | invokedynamic= 186 (0xba) |
Стек операндов | ..., [арг1, [арг2...]] →
... |
Описание | Каждое использование инструкции invokedynamic называется динамическим узлом вызова.
Сначала беззнаковые байт_индекса1 и байт_индекса2 используются для построения индекса массива в константном пуле времени выполнения текущего класса (см. §2.6). Значение индекса определяется как (байт_индекса1 << 8)|(байт_индекса2). Элемент константного пула с найденным индексом должен быть символьной ссылкой на спецификатор узла вызова (см. §5.1). Значения третьего и четвёртого операнда должны всегда быть равны нулю. Спецификатор узла вызова разрешается (см. §5.4.3.6) для данного конкретного динамического узла вызова, чтобы получить ссылку типа reference на экземпляр java.lang.invoke.MethodHandle, ссылку типа reference на экземпляр java.lang.invoke.MethodType и набор ссылок типа reference на статические аргументы. Затем, как часть процесса разрешения спецификатора узла вызова, вызывается инициализирующий метод. Как будто была бы вызвана инструкция invokevirtual с указанием ей индекса элемента константного пула, являющегося символьной ссылкой на метод, (см. §5.1) со следующими свойствами:
При этом как будто следующие элементы были бы записаны в стек операндов в указанном порядке:
До тех пор пока инициализирующий метод может быть корректно вызван метода invoke, его дескриптор произволен. Например, первый параметр мог бы быть Object вместо java.lang.invoke.MethodHandles.Lookup, а возвращаемый тип также мог бы быть Object вместо java.lang.invoke.CallSite. Если инициализирующий метод имеет переменное число параметров, тогда некоторые (или все) аргументы в стеке операндов могут быть собраны в массив параметров соответствующего типа. Вызов инициализирующего метода происходит в потоке, который выполняет разрешение символьной ссылки спецификаторы узла вызова. Если таких потоков несколько, инициализирующий метод может быть вызван в нескольких потоках одновременно. Поэтому инициализирующие методы, обращающиеся к глобальным данным приложения, должны содержать защиту от такой ошибки многопоточной работы приложения как состояние гонок (конкуренция за ресурсы). Результат, возвращаемый инициализирующим методом должен быть ссылкой (тип reference) на объект класса java.lang.invoke.CallSite или его наследника. Этот объект называется объектом узла вызова. Эта ссылка считывается из стека операндов также как и при работе инструкции invokevirtual. Если несколько потоков одновременно исполняют инициализирующий метод для одного и того же динамического узла вызова, то виртуальная машина Java должна определить один объект узла вызова и сделать его видимым всем потокам. Допустимо продолжать выполнение остальных инициализирующих методов, но результаты их выполнения не будут использованы, и выполнение потока динамического узла вызова продолжится с выбранным ранее объектом узла вызова. Объект узла вызова также является дескриптором (экземпляр java.lang.invoke.MethodType), который должен быть семантически равным дескриптору метода в спецификаторе узла вызова. Результатом успешного разрешения спецификатора узла вызова является объект узла вызова, связанный перманентно с динамическим узлом вызова. Затем вызывается обработчик метода, описанного в целевом объекте узла вызова. Вызов происходит эквивалентно вызову инструкции invokevirtual с указанием ей индекса элемента константного пула, являющегося символьной ссылкой на метод, (см. §5.1) со следующими свойствами:
Содержимое стека операндов может быть интерпретировано следующим образом: считается, что в стеке есть ссылка (типа reference) на целевой объект узла вызова, за которым следуют значения аргументов, число, тип и порядок которых должны соответствовать дескриптору метода в спецификаторе узла вызова. |
Исключения связывания | Если при разрешении символьной ссылки на спецификатор узла вызова возникает исключение E, инструкция invokedynamic генерирует BootstrapMethodError, оборачивая в него исходное исключение.
Если же при вызове инициализирующего метода он завершается аварийно (§2.6.5) из-за возникновения исключения E, invokedynamic также выбрасывает BootstrapMethodError, оборачивая в него исходное исключение. (Это может произойти, если инициализирующий метод имеет неверное количество параметров, несовпадающие типы параметров или тип возвращаемого значения. В этом случае 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 |
Операция | Вызывает метод интерфейса |
Формат |
|
Формы | invokeinterface= 185 (0xb9) |
Стек операндов | ...,ссылка на объект, [арг1, [арг2...]] →
... |
Описание | Беззнаковые байт_индекса1 и байт_индекса2 используются для построения индекса массива в константном пуле времени выполнения текущего класса (см. §2.6). Значение индекса определяется как (байт_индекса1 << 8)|(байт_индекса2). Элемент константного пула с найденным индексом должен быть символьной ссылкой на метод интерфейса (см. §5.1). Этот элемент содержит имя и дескриптор метода (см. §4.3.3) а также символьную ссылку на интерфейс, в котором данный метод может быть найден. Указанный интерфейсный метод разрешается (см. §5.4.3.4). Разрешенный интерфейсный метод не должен быть методом инициализации экземпляра (конструктором, см. §2.9), а также не должен быть методом инициализации класса или интерфейса (см. §2.9).
Счётчик - это беззнаковый байт, не равный нулю. Ссылка на объект должна принадлежать типу reference, и должна предшествовать в стеке операндов значениям аргументов, причём их число, тип и порядок следования должны соответствовать числу, типу и порядку в дескрипторе разрешённого метода. Значение четвёртого байта операндов должно быть всегда равно нулю. Пусть C - это класс, на экземпляр которого ссылается ссылка на объект. Фактический метод для вызова выбирается по следующей процедуре:
Если метод объявлен с модификатором synchronized, то выполняется захват (или повторный захват) монитора связанного со ссылкой объект (как при выполнении инструкции monitorenter для текущего потока). Если метод объявлен без модификатора native, то аргументы и ссылка на объект считываются из стека операндов. Для метода, который подлежит вызову, создаётся новый фрейм в стеке виртуальной машины Java. Ссылка на объект и значения аргументов записываются в локальные переменные нового фрейма, причём ссылка на объект записывается в локальную переменную 0, первый аргумент - в локальную переменную 1 (если первый аргумент принадлежит типу long или double, то он записывается в локальные переменные 1 и 2) и так далее. Все аргументы, принадлежащие типам данных с плавающей точкой, подвергаются серии преобразований (см. §2.8.3) прежде чем будут сохранены в локальных переменных. Созданный фрейм становится текущим и регистр pc виртуальной машины Java устанавливается так, что бы указывать на индекс первой инструкции вызываемого метода. Выполнение инструкций продолжается с первой инструкции метода. Если метод объявлен с модификатором native, то и платформенно зависимый код, который реализует метод, ещё не был привязан к виртуальной машине Java (§5.6), то такая привязка происходит. Аргументы и ссылка на объект считываются из стека операндов и передаются как параметры в код, реализующий метод. Все аргументы, принадлежащие типам данных с плавающей точкой, подвергаются серии преобразований (см. §2.8.3) прежде чем будут переданы в качестве параметров. Затем происходит передача параметров и вызов платформенно зависимого кода. Когда платформенно зависимый метод завершает выполнение:
|
Исключения связывания | Может быть выброшено любое исключение, которое может возникнуть при разрешении символьной ссылки на интерфейсный метод (§5.4.3.4). |
Исключения времени выполнения | Если ссылка на объект равна null, то invokeinterface генерирует исключение NullPointerException.
Если класс, на который ссылается ссылка на объект не имплементирует интерфейс, то invokeinterface генерирует IncompatibleClassChangeError. Если нет ни одного метода с заданным именем и дескриптором, то invokeinterface генерирует AbstractMethodError. Если выбранный метод не является public, invokeinterface генерирует IllegalAccessError. Если выбранный метод объявлен с модификатором abstract, invokeinterface генерирует AbstractMethodError. Если выбранный метод объявлен как native и код, который его имплементирует не может быть найден, то invokeinterface генерирует UnsatisfiedLinkError. |
Примечания | Параметр счётчик инструкции invokeinterface содержит количество локальных переменных, которые нужно создать для хранения аргументов метода. Причём аргументы с типами long и double увеличивают счётчик на две единицы, аргументы всех остальных типов увеличивают счётчик на единицу. Эта информация также может быть получена из дескриптора выбранного метода. Такое дублирование сохранено по историческим причинам.
Четвёртый (имеющий значение 0) байт резервирует место для дополнительно операнда, который используется в некоторых имплементациях виртуальной машины компании Oracle. В таких имплементациях инструкция invokeinterface заменяется во время выполнения специальной псевдокомандой. Байт должен быть зарезервирован для обратной совместимости. Значения n аргументов и ссылка на объект не взаимно однозначно соответствуют первым n +1 локальным переменным. Аргументы с типами long и double должны быть сохранены в двух локальных переменных с последовательными индексами, поэтому для хранения n аргументов может понадобится более чем n локальных переменных. |
invokespecial | invokespecial |
Операция | Вызывает метод экземпляра; используется при вызове методов класса-предка, приватных методов и методов, инициализирующих экземпляр |
Формат |
|
Формы | invokespecial= 183 (0xb7) |
Стек операндов | ..., ссылка на объект, [арг1, [арг2...]] →
... |
Описание | Беззнаковые байт_индекса1 и байт_индекса2 используются для построения индекса массива в константном пуле времени выполнения текущего класса (см. §2.6). Значение индекса определяется как (байт_индекса1 << 8)|(байт_индекса2). Элемент константного пула с найденным индексом должен быть символьной ссылкой на метод (см. §5.1). Этот элемент содержит имя и дескриптор метода (см. §4.3.3) а также символьную ссылку на класс, в котором данный метод может быть найден. Указанный метод разрешается (см. §5.4.3.4). Если разрешенный метод объявлен с модификатором protected (см. §4.6) и принадлежит предку текущего класса и при этом в текущем классе он не объявлен, то ссылка на объект должна ссылаться либо на объект текущий класса либо на объект его наследника.
Если все условия, перечисленные ниже, истинные, то управление передаётся разрешённому методу.
Затем происходит поиск метода, который будет в действительности вызван. Пусть C - это класс-предок, текущего класса. Фактический метод для вызова выбирается по следующей процедуре:
Ссылка на объект должна принадлежать типу reference. За ней в стеке операндов следуют значения аргументов, причём их число, тип и порядок должны соответствовать числу, типу и порядку в дескрипторе выбранного метода. Если метод объявлен без модификатора native, то аргументы и ссылка на объект считываются из стека операндов. Для метода, который подлежит вызову, создаётся новый фрейм в стеке виртуальной машины Java. Ссылка на объект и значения аргументов записываются в локальные переменные нового фрейма, причём ссылка на объект записывается в локальную переменную 0, первый аргумент - в локальную переменную 1 (если первый аргумент принадлежит типу long или double, то он записывается в локальные переменные 1 и 2) и так далее. Все аргументы, принадлежащие типам данных с плавающей точкой, подвергаются серии преобразований (см. §2.8.3) прежде чем будут сохранены в локальных переменных. Созданный фрейм становится текущим и регистр pc виртуальной машины Java устанавливается так, что бы указывать на индекс первой инструкции вызываемого метода. Выполнение инструкций продолжается с первой инструкции метода. Если метод объявлен с модификатором native, то и платформенно зависимый код, который реализует метод, ещё не был привязан к виртуальной машине Java (§5.6), то такая привязка происходит. Аргументы и ссылка на объект считываются из стека операндов и передаются как параметры в код, реализующий метод. Все аргументы, принадлежащие типам данных с плавающей точкой, подвергаются серии преобразований (см. §2.8.3) прежде чем будут переданы в качестве параметров. Затем происходит передача параметров и вызов платформенно зависимого кода. Когда платформенно зависимый метод завершает выполнение:
|
Исключения связывания | Может быть выброшено любое исключение, которое может возникнуть при разрешении символьной ссылки на метод (§5.4.3.3).
Если разрешенный метод является инициализирующим методом экземпляра и класс, в котором он объявлен не является тем классом, на который (после разрешения метода) ссылается инструкция invokespecial, то генерируется исключение NoSuchMethodError. Если разрешенный метод принадлежит классу (static) , то invokespecial генерирует исключение IncompatibleClassChangeError. |
Исключения времени выполнения | Если ссылка на объект равна null, то invokespecial генерирует исключение NullPointerException.
Если нет ни одного метода с заданным именем и дескриптором, то invokespecial генерирует AbstractMethodError. Если выбранный метод объявлен с модификатором abstract, invokespecial генерирует AbstractMethodError. Если выбранный метод объявлен как native и код, который его имплементирует не может быть найден, то invokespecial генерирует UnsatisfiedLinkError. |
Примечания | Разница между инструкциями invokespecial и invokevirtual в том, что invokevirtual вызывает метод, основываясь на классе объекта. Инструкция invokespecial используется для вызова методов инициализирующих экземпляр (см. §2.9) а также для методов с модификатором private и методов класса предка.
|
invokestatic | invokestatic |
Операция | Вызывает метод класса (static) |
Формат |
|
Формы | invokestatic= 184 (0xb8) |
Стек операндов | ..., [арг1, [арг2...]]→
... |
Описание | Беззнаковые байт_индекса1 и байт_индекса2 используются для построения индекса массива в константном пуле времени выполнения текущего класса (см. §2.6). Значение индекса определяется как (байт_индекса1 << 8)|(байт_индекса2). Элемент константного пула с найденным индексом должен быть символьной ссылкой на метод интерфейса (см. §5.1). Этот элемент содержит имя и дескриптор метода (см. §4.3.3) а также символьную ссылку на класс, в котором данный метод может быть найден. Указанный метод разрешается (см. §5.4.3.4). Разрешенный метод не должен быть методом инициализации экземпляра (конструктором, см. §2.9), а также не должен быть методом инициализации класса или интерфейса (см. §2.9). Он должен быть статическим и поэтому не может быть абстрактным.
При успешном разрешении метода класс, содержащий объявленный метод инициализируется (см. §5.5), если до этого он не был инициализирован. Стек операндов должен содержать значения аргументов, причём их число, тип и порядок должны соответствовать числу, типу и порядку указанному в дескрипторе разрешённого метода. Если метод объявлен с модификатором synchronized, то монитор объекта класса Class захватывается впервые (или повторно) как при выполнении инструкции monitorenter для текущего потока. Если метод объявлен без модификатора native, то аргументы и ссылка на объект считываются из стека операндов. Для метода, который подлежит вызову, создаётся новый фрейм в стеке виртуальной машины Java. Ссылка на объект и значения аргументов записываются в локальные переменные нового фрейма, причём ссылка на объект записывается в локальную переменную 0, первый аргумент - в локальную переменную 1 (если первый аргумент принадлежит типу long или double, то он записывается в локальные переменные 1 и 2) и так далее. Все аргументы, принадлежащие типам данных с плавающей точкой, подвергаются серии преобразований (см. §2.8.3) прежде чем будут сохранены в локальных переменных. Созданный фрейм становится текущим и регистр pc виртуальной машины Java устанавливается так, что бы указывать на индекс первой инструкции вызываемого метода. Выполнение инструкций продолжается с первой инструкции метода. Если метод объявлен с модификатором native, то и платформенно зависимый код, который реализует метод, ещё не был привязан к виртуальной машине Java (§5.6), то такая привязка происходит. Аргументы и ссылка на объект считываются из стека операндов и передаются как параметры в код, реализующий метод. Все аргументы, принадлежащие типам данных с плавающей точкой, подвергаются серии преобразований (см. §2.8.3) прежде чем будут переданы в качестве параметров. Затем происходит передача параметров и вызов платформенно зависимого кода. Когда платформенно зависимый метод завершает выполнение:
|
Исключения связывания | Может быть выброшено любое исключение, которое может возникнуть при разрешении символьной ссылки на метод (§5.4.3.3).
Если разрешенный метод принадлежит объекту, то invokestatic генерирует исключение IncompatibleClassChangeError. |
Исключения времени выполнения | Если выполнение invokestatic приводит к инициализации класса, то может быть выброшена ошибка, более детально описанная в §5.5.
Если выбранный метод объявлен как native и код, который его имплементирует не может быть найден, то invokestatic генерирует UnsatisfiedLinkError. |
Примечания | Значения n аргументов не взаимно однозначно соответствуют первым n локальным переменным. Аргументы с типами long и double должны быть сохранены в двух локальных переменных с последовательными индексами, поэтому для хранения n аргументов может понадобится более чем n локальных переменных. |
invokevirtual | invokevirtual |
Операция | Вызывает метод экземпляра; диспетчеризация основана на классах |
Формат |
|
Формы | invokevirtual= 182 (0xb6) |
Стек операндов | ..., ссылка на объект, [арг1, [арг2...]] →
... |
Описание | Беззнаковые байт_индекса1 и байт_индекса2 используются для построения индекса массива в константном пуле времени выполнения текущего класса (см. §2.6). Значение индекса определяется как (байт_индекса1 << 8)|(байт_индекса2). Элемент константного пула с найденным индексом должен быть символьной ссылкой на метод интерфейса (см. §5.1). Этот элемент содержит имя и дескриптор метода (см. §4.3.3) а также символьную ссылку на класс, в котором данный метод может быть найден. Указанный метод разрешается (см. §5.4.3.4). Разрешенный метод не должен быть методом инициализации экземпляра (конструктором, см. §2.9), а также не должен быть методом инициализации класса или интерфейса (см. §2.9). Если разрешенный метод объявлен с модификатором protected (см. §4.6) и принадлежит предку текущего класса и при этом в текущем классе он не объявлен, то ссылка на объект должна ссылаться либо на объект текущий класса либо на объект его наследника.
Если разрешенный метод не является сигнатурно полиморфным (см. §2.9) тогда выполнение инструкции invokevirtual продолжается следующим образом. Пусть C - это класс, на экземпляр которого ссылается ссылка на объект. Фактический метод для вызова выбирается по следующей процедуре:
Ссылка на объект должна принадлежать типу reference. За ней в стеке операндов следуют значения аргументов, причём их число, тип и порядок должны соответствовать числу, типу и порядку в дескрипторе выбранного метода. Если метод объявлен без модификатора native, то аргументы и ссылка на объект считываются из стека операндов. Для метода, который подлежит вызову, создаётся новый фрейм в стеке виртуальной машины Java. Ссылка на объект и значения аргументов записываются в локальные переменные нового фрейма, причём ссылка на объект записывается в локальную переменную 0, первый аргумент - в локальную переменную 1 (если первый аргумент принадлежит типу long или double, то он записывается в локальные переменные 1 и 2) и так далее. Все аргументы, принадлежащие типам данных с плавающей точкой, подвергаются серии преобразований (см. §2.8.3) прежде чем будут сохранены в локальных переменных. Созданный фрейм становится текущим и регистр pc виртуальной машины Java устанавливается так, что бы указывать на индекс первой инструкции вызываемого метода. Выполнение инструкций продолжается с первой инструкции метода. Если метод объявлен с модификатором native, то и платформенно зависимый код, который реализует метод, ещё не был привязан к виртуальной машине Java (§5.6), то такая привязка происходит. Аргументы и ссылка на объект считываются из стека операндов и передаются как параметры в код, реализующий метод. Все аргументы, принадлежащие типам данных с плавающей точкой, подвергаются серии преобразований (см. §2.8.3) прежде чем будут переданы в качестве параметров. Затем происходит передача параметров и вызов платформенно зависимого кода. Когда платформенно зависимый метод завершает выполнение:
Если разрешенный метод является сигнатурно полиморфным (см. §2.9) тогда выполнение инструкции invokevirtual продолжается следующим образом. Сначала формируется ссылка (тип reference) на экземпляр java.lang.invoke.MethodType как при разрешении символьной ссылки на тип метода (см. §5.4.3.5) с такими же параметрами и возвращаемым типом как и в дескрипторе метода, полученного по ссылке инструкции invokevirtual.
В стеке операндов за ссылкой на объект должны следовать значения аргументов прим их число, тип и порядок следования должны соответствовать числу, типу и порядку следования описанному в дескрипторе типа вызываемого метода. (Дескриптор типа должен соответствовать дескриптору метода (с учётом типа обработчика метода), как указано в §5.4.3.5.) Далее, если обработчик метода, который необходимо вызвать, реализован в виде байт-кода, виртуальная машина Java выполняет обработчик метода с учётом типа обработчика метода. Если тип обработчика метода есть 5 (REF_invokeVirtual), 6 (REF_invokeStatic), 7 (REF_invokeSpecial), 8 (REF_newInvokeSpecial) или 9 (REF_invokeInterface), то создаётся фрейм и назначается текущим для выполнения соответствующего байт кода. Когда метод, выполняющий байт код завершается (нормально или аварийно), то фрейм вызвавшего его метода считается фреймом, содержащим инструкцию invokevirtual.
|
Исключения связывания | Может быть выброшено любое исключение, которое может возникнуть при разрешении символьной ссылки на метод (§5.4.3.3).
Если разрешенный метод является статическим, то invokevirtual генерирует исключение IncompatibleClassChangeError. Если разрешенный метод является сигнатурно полиморфным, то во время разрешения типа метода, полученного из дескриптора по символьной ссылке на метод, могут быть сгенерированы любые исключения, связанные с разрешением типов (см. §5.4.3.5) |
Исключения времени выполнения | Если ссылка на объект есть null, то инструкция invokevirtual генерирует NullPointerException.
Если разрешенный метод не является сигнатурно полиморфным:
Если разрешенный метод является сигнатурно полиморфным:
|
Примечания | Значения n аргументов и ссылка на объект не взаимно однозначно соответствуют первым n +1 локальным переменным. Аргументы с типами long и double должны быть сохранены в двух локальных переменных с последовательными индексами, поэтому для хранения n аргументов может понадобится более чем n локальных переменных. |
ior | ior |
Операция | Логическое «или» над значениями типа int |
Формат |
|
Формы | ior= 128 (0x80) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу int. Они считываются из стека операндов. Результат также принадлежит типу int и представляет собой побитовое "ИЛИ" над значением1 и значением2. Затем результат записывается в стек операндов. |
irem | irem |
Операция | Остаток от деления значений типа int |
Формат |
|
Формы | irem= 112 (0x70) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу int. Они считываются из стека операндов. Результат также принадлежит типу int и представляет собой значение1 - (значение1 / значение2) * значение2. Затем результат записывается в стек операндов.
Результат инструкции irem это величина такая, что (a/b)*b + (a%b) равна a. Это равенство справедливо даже в специальных случаях, когда делимое есть отрицательное целое, максимальное по модулю, а делитель есть -1 (при этом остаток есть 0). Из равенства следует также что результат операции отрицателен, если делимое отрицательно и положителен, если делимое положительно. Более того, результат всегда меньше чем делитель. |
Исключения времени выполнения | Если делитель равен нулю, то инструкция irem генерирует ArithmeticException. |
ireturn | ireturn |
Операция | Возвращает значение типа int из метода |
Формат |
|
Формы | ireturn= 172 (0xac) |
Стек операндов | ..., значение →
[пусто] |
Описание | Текущий метод должен возвращать величину типа boolean, byte, short, char или int. Значение должно принадлежать int. Если текущий метод объявлен с ключевым словом synchronized, то при входе в метод монитор захватывается первоначально (либо повторно, если уже был захвачен до того), а при выходе освобождается, как при выполнении инструкции monitorexit для текущего потока. Если в ходе выполнения метода не было исключений, значение считывается из стека операндов текущего фрейма (см. §2.6) Затем значение записывается в стек операндов фрейма, принадлежащего вызывающему методу. Все остальные значения стека операндов текущего фрейма теряются.
Затем интерпретатор передаёт управление вызывающему методу, делая текущим соответствующий фрейм. |
Исключения времени выполнения | Если реализация виртуальной машины Java не поддерживает правила структурных блокировок описанные в §2.11.10, тогда если текущий метод объявлен как synchronized и текущий поток не является владельцем монитора, захваченного при входе в метод, то при вызове ireturn будет выброшено исключение IllegalMonitorStateException. Это может произойти, если synchronized-метод содержит инструкцию monitorexit, а инструкция monitorenter по объекту синхронизации отсутствует.
С другой стороны, если реализация виртуальной машины Java поддерживает правила структурных блокировок описанные в §2.11.10, и во время выполнения текущего метода нарушено первое из этих правил, то при вызове ireturn будет выброшено исключение IllegalMonitorStateException. |
ishl | ishl |
Операция | Сдвиг влево значения типа int |
Формат |
|
Формы | ishl= 120 (0x78) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу int. Они считываются из стека операндов. Результат также принадлежит типу int и представляет собой значение1 сдвинутое влево на s позиций, где s – это младшие 5 битов значения2. Затем результат записывается в стек операндов. |
Примечания | Операция сдвига влево эквивалентна (даже в случае переполнения) умножению исходного значения на 2 в степени s. Количество бит, на которое нужно сдвинуть значение, всегда находится в пределах от 0 до 31 включительно, как если бы до сдвига над значением2 было выполнено логическое «И» с маской 0x1f. |
ishr | ishr |
Операция | Арифметический сдвиг вправо значения типа int |
Формат |
|
Формы | ishr= 122 (0x7a) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу int. Они считываются из стека операндов. Результат также принадлежит типу int и представляет собой значение1 сдвинутое вправо на s позиций, где s – это младшие 5 битов значения2. Затем результат записывается в стек операндов. |
Примечания | Операция сдвига вправо возвращает значение равное ⌊значение1/ 2s⌋, где s - это значение2 & 0x1f. Если значение1 не отрицательно, то сдвиг эквивалентен целочисленному делению значения1 на 2 в степени s с отбрасыванием дробной части результата. Количество бит, на которое нужно сдвинуть значение, всегда находится в пределах от 0 до 31 включительно, как если бы до сдвига над значением2 было выполнено логическое «И» с маской 0x1f. |
istore | istore |
Операция | Считывает из стека значение типа int и записывает в локальную переменную |
Формат |
|
Формы | istore= 54 (0x36) |
Стек операндов | ..., значение →
... |
Описание | Индекс является беззнаковым байтом. Индекс должен принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Значение на вершине стека операндов должно принадлежать типу int. Оно считывается из стека операндов, затем в локальную переменную с индексом индекс записывается значение. |
Примечания | Инструкция istore может быть использована совместно с инструкцией wide, когда необходимо задать двухбайтовый беззнаковый индекс локальной переменной. |
istore_<n> | istore_<n> |
Операция | Считывает из стека значение типа int и записывает в локальную переменную |
Формат |
|
Формы | istore_0= 59 (0x3b)
istore_1= 60 (0x3c) istore_2= 61 (0x3d) istore_3= 62 (0x3e) |
Стек операндов | ..., значение →
... |
Описание | <n>должно принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Значение на вершине стека операндов должно принадлежать типу int. Оно считывается из стека операндов, затем в локальную переменную с индексом <n>записывается значение. |
Примечания | Каждая из инструкции istore_<n> выполняет то же, что и istore с явным индексом <n> за исключением того, что операнд <n> задан не явно. |
isub | isub |
Операция | Вычитает значения типа int |
Формат |
|
Формы | isub= 100 (0x64) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу int. Они считываются с вершины стек операндов. Результат типа int есть значение1 - значение2. Результат записывается в стек операндов.
Для целочисленного вычитания выражение a-b дает такой же результат, что и a+(-b). Для значений типа int вычитание из нуля есть то же самое, что и отрицание числа. Результат вычитания - это младшие 32 бита результата точного вычитания, представленные в двоичном дополнительном коде. Если происходит переполнение, то знак результата может отличаться от знака математической разности двух значений. Не смотря на то, что при выполнении инструкции isub может произойти переполнение, инструкция isub никогда не приводит к исключению времени выполнения. |
iushr | iushr |
Операция | Логический сдвиг вправо значения типа int |
Формат |
|
Формы | 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 | ixor |
Операция | Исключающее «или» над значениями типа int |
Формат |
|
Формы | ixor= 130 (0x82) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу int. Они считываются из стека операндов. Результат также принадлежит типу int и представляет собой результат операции «исключающее ИЛИ» над значением1 и значением2. Затем результат записывается в стек операндов. |
jsr | jsr |
Операция | Вызов подпрограммы |
Формат |
|
Формы | jsr= 168 (0xa8) |
Стек операндов | ...→
..., адрес |
Описание | Адрес перехода, который следует непосредственно за инструкцией jsr, записывается в стек операндов как значение типа returnAddress. Беззнаковые байт_адреса1 и байт_адреса2 используются для построения знакового 16-ти битового смещения, которое вычисляется следующим образом: (байт_адреса1 << 8) | байт_адреса2. Затем выполнение инструкций продолжается со смещения, вычисленного ранее относительно инструкции jsr. Целевой адрес перехода должен быть в пределах метода, содержащего инструкцию jsr. |
Примечания | Обратите внимание, что jsr записывает адрес в стек операндов, а инструкция ret берет его из локальной переменной. Эта асимметрия сделана сознательно.
В реализации компилятора виртуальной машины Java от компании Oracle до Java SE 6 инструкция jsr использовалась совместно с инструкцией ret в блоке finally (см. §3.13, §4.10.2.5). |
jsr_w | jsr_w |
Операция | Вызов подпрограммы (расширенный индекс) |
Формат |
|
Формы | jsr_w= 201 (0xc9) |
Стек операндов | ...→
..., адрес |
Описание | Адрес перехода, который следует непосредственно за инструкцией jsr_w, записывается в стек операндов как значение типа returnAddress. Беззнаковые байт_адреса1, байт_адреса2, байт_адреса3 и байт_адреса4 используются для построения 32-битового знакового смещения перехода (байт_адреса1 << 24) | (байт_адреса2 << 16) (байт_адреса3 << 8) | байт_адреса4. Затем выполнение инструкций продолжается со смещения, вычисленного ранее относительно инструкции jsr_w. Целевой адрес перехода должен быть в пределах метода, содержащего инструкцию jsr_w. |
Примечания | Обратите внимание, что jsr_w записывает адрес в стек операндов, а инструкция ret берет его из локальной переменной. Эта асимметрия сделана сознательно.
В реализации компилятора виртуальной машины Java от компании Oracle до Java SE 6 инструкция jsr_w использовалась совместно с инструкцией ret в блоке finally (см. §3.13, §4.10.2.5). Хотя инструкция jsr_w принимает на вход 4-х байтовое смещение, ограничивающим фактором для перехода является также размер метода, равный 65535 байтам (см. §4.11). Это ограничение может быть снято в последующих версиях виртуальной Java машины. |
l2d | l2d |
Операция | Преобразует значение типа long к типу double |
Формат |
|
Формы | l2d= 138 (0x8a) |
Стек операндов | ..., значение →
..., результат |
Описание | Значение на вершине стека операндов должно принадлежать типу long. Оно считывается с вершины стека операндов и преобразуется к результату типа double, согласно правилам округления к ближайшему стандарта IEEE 754. Результат записывается в стек операндов. |
Примечания | Инструкция l2d выполняет расширяющее преобразование примитивных типов (см. JLS §5.1.2), что может привести к потере точности, поскольку мантисса числа типа double имеет только 53 значащих бита. |
l2f | l2f |
Операция | Преобразует значение типа long к типу float |
Формат |
|
Формы | l2f= 137 (0x89) |
Стек операндов | ..., значение →
..., результат |
Описание | Значение на вершине стека операндов должно принадлежать типу long. Оно считывается с вершины стека операндов и преобразуется к результату типа float, согласно правилам округления к ближайшему стандарта IEEE 754. Результат записывается в стек операндов. |
Примечания | Инструкция l2f выполняет расширяющее преобразование примитивных типов (см. JLS §5.1.2), что может привести к потере точности, поскольку мантисса числа типа float имеет только 24 значащих бита. |
l2i | l2i |
Операция | Преобразует значение типа long к типу int |
Формат |
|
Формы | l2i= 136 (0x88) |
Стек операндов | ..., значение →
..., результат |
Описание | Значение на вершине стека операндов должно принадлежать типу long. Оно считывается с вершины стека операндов и преобразуется к результату типа int, следующим образом: в качестве результата берутся младшие 32 бита значения long, старшие 32 бита игнорируются. Результат записывается в стек операндов. |
Примечания | Инструкция l2i выполняет сужающее преобразование примитивных типов (см. JLS §5.1.2), что может привести к полной потере исходного значения. Знак результата также может отличаться от знака исходного значения. |
ladd | ladd |
Операция | Складывает два значения типа long |
Формат |
|
Формы | ladd= 97 (0x61) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу long. Они считываются с вершины стек операндов. Результат типа long есть значение1 + значение2. Результат записывается в стек операндов.
Результат сложения - это младшие 64 бита результата точного сложения, представленные в двоичном дополнительном коде. Если происходит переполнение, то знак результата может отличаться от знака математической суммы двух значений. Не смотря на то, что при выполнении инструкции ladd может произойти переполнение, инструкция ladd никогда не приводит к исключению времени выполнения. |
laload | laload |
Операция | Записывает в стек значение long из массива |
Формат |
|
Формы | laload= 47 (0x2f) |
Стек операндов | ..., ссылка на массив, индекс →
..., значение |
Описание | Ссылка на массив должна быть типа reference и ссылаться на массив, чьи компоненты значения типа long. Индекс должен принадлежать типу int. Как ссылка на массив, так и индекс считываются из стека операндов. Значение типа long считывается из элемента массива с соответствующим индексом и записывается в стек операндов. |
Исключения времени выполнения | Если ссылка на массив равна null, то laload генерирует NullPointerException. В противном случае, если индекс вне границ массива, генерируется исключение ArrayIndexOutOfBoundsException. |
land | land |
Операция | Булево «И» над значениями типа long |
Формат |
|
Формы | land= 127 (0x7f) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу long. Они считываются с вершины стека операндов. Результат типа long есть логическое "И" над значением1 и значеним2. Результат записывается в стек операндов. |
lastore | lastore |
Операция | Загружает значение типа long из стека в массив |
Формат |
|
Формы | lastore= 80 (0x50) |
Стек операндов | ..., ссылка на массив, индекс, значение →
... |
Описание | Ссылка на массив должна быть типа reference и ссылаться на массив, чьи компоненты значения типа long. Индекс должен принадлежать типу int, значение должно принадлежать типу long. Ссылка на массив, индекс и значение считываются из стека операндов. Затем значение сохраняется в массиве с заданным индексом. |
Исключения времени выполнения | Если ссылка на массив равна null, то lastore генерирует NullPointerException. В противном случае, если индекс вне границ массива, генерируется исключение ArrayIndexOutOfBoundsException. |
lcmp | lcmp |
Операция | Сравнивает два значения типа long |
Формат |
|
Формы | lcmp= 148 (0x94) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу long. Они считываются с вершины стека операндов, затем выполняется знаковое сравнение этих чисел. Если значение1 больше чем значение2, то результат типа int есть 1, записанная в стек операндов. Если значение1 равно значению2, то результат типа int есть 0, записанный в стек операндов. Если значение1 меньше чем значение2, то результат типа int есть -1, записанная в стек операндов. |
lconst_<l> | lconst_<l> |
Операция | Записывает в стек константу типа long |
Формат |
|
Формы | lconst_0= 9 (0x9)
lconst_1= 10 (0xa) |
Стек операндов | ...→
..., <l> |
Описание | Записывает константу <l> (0 или 1) типа long в стек операндов. |
ldc | ldc |
Операция | Записывает элемент из константного пула времени выполнения в стек |
Формат |
|
Формы | ldc= 18 (0x12) |
Стек операндов | ...→
..., значение |
Описание | Индекс является беззнаковым байтом и представляет собой действительный индекс элемента константного пула текущего класса (см. §2.6). Элемент константного пула с заданным индексом должен принадлежать типу int, float, или быть ссылкой (reference) на строковый литерал; либо быть символьной ссылкой на класс, тип метода или обработчик метода (см. §5.1).
Если элемент константного пула есть величина с типом int или float, то значение этой величины записывается в стек операндов с типом int или float соответственно. Если элемент константного пула есть ссылка (reference) на экземпляр класса String, (строковый литерал, см. §5.1), то значение ссылки записывается в стек операндов. Если элемент константного пула есть символьная ссылка на класс (см. §5.1), то названный класс разрешается (см. §5.4.3.1) и ссылка (тип reference) на экземпляр класса Class записывается в стек операндов. Если элемент константного пула есть символьная ссылка на тип метода или обработчик метода (см. §5.1), то тип метода или обработчик метода разрешается (см. §5.4.3.5) и ссылка (тип reference) на экземпляр java.lang.invoke.MethodType или java.lang.invoke.MethodHandle записывается в стек операндов. |
Исключения связывания | Во время разрешения символьной ссылки на класс, может быть создано любое исключение, описанное в (§5.4.3.1).
Во время разрешения символьной ссылки на тип метода или обработчик метода, может быть создано любое исключение, описанное в (§5.4.3.5) |
Примечания | Инструкция ldc может быть использована для записи в стек значений типа float только принадлежащий множеству значений с плавающей точкой (см. §2.3.2), поскольку величина float в константном пуле (см. §4.4.4) также принадлежит этому множеству. |
ldc_w | ldc_w |
Операция | Записывает элемент из константного пула времени выполнения в стек (расширенный индекс) |
Формат |
|
Формы | ldc_w= 19 (0x13) |
Стек операндов | ...→
..., значение |
Описание | Беззнаковый байт_индекса1 и байт_индекса2 преобразуются в 16-ти битный беззнаковый индекс элемента константного пула текущего класса (см. §2.6). Значение индекса вычисляется следующим образом: (байт_индекса1 << 8)|байт_индекса2. Элемент константного пула с заданным индексом должен принадлежать типу int, float, или быть ссылкой (reference) на строковый литерал; либо быть символьной ссылкой на класс, тип метода или обработчик метода (см. §5.1).
Если элемент константного пула есть величина с типом int или float, то значение этой величины записывается в стек операндов с типом int или float соответственно. Если элемент константного пула есть ссылка (reference) на экземпляр класса String, (строковый литерал, см. §5.1), то значение ссылки записывается в стек операндов. Если элемент константного пула есть символьная ссылка на класс (см. §5.1), то названный класс разрешается (см. §5.4.3.1) и ссылка (тип reference) на экземпляр класса Class записывается в стек операндов. Если элемент константного пула есть символьная ссылка на тип метода или обработчик метода (см. §5.1), то тип метода или обработчик метода разрешается (см. §5.4.3.5) и ссылка (тип reference) на экземпляр java.lang.invoke.MethodType или java.lang.invoke.MethodHandle записывается в стек операндов. |
Исключения связывания | Во время разрешения символьной ссылки на класс, может быть создано любое исключение, описанное в (§5.4.3.1).
Во время разрешения символьной ссылки на тип метода или обработчик метода, может быть создано любое исключение, описанное в (§5.4.3.5) |
Примечания | Инструкция ldc_w полностью идентична инструкции ldc за исключением того, что использует индекс элемента константного пула с более широким диапазоном.
Инструкция ldc_w может быть использована для записи в стек значений типа float только принадлежащий множеству значений с плавающей точкой (см. §2.3.2), поскольку величина float в константном пуле (см. §4.4.4) также принадлежит этому множеству. |
ldc2_w | ldc2_w |
Операция | Записывает значение типа long или double из константного пула времени выполнения в стек (расширенный индекс) |
Формат |
|
Формы | ldc2_w= 20 (0x14) |
Стек операндов | ...→
..., значение |
Описание | Беззнаковый байт_индекса1 и байт_индекса2 преобразуются в 16-ти битный беззнаковый индекс элемента константного пула текущего класса (см. §2.6). Значение индекса вычисляется следующим образом: (байт_индекса1 << 8)|байт_индекса2. Элемент константного пула с заданным индексом должен принадлежать типу long или double (см. §5.1). Элемент константного пула записывается в стек операндов как long или double соответственно. |
Примечания | Для инструкции ldc2_w существует только версия с использованием двухбайтового расширенного индекса. Инструкции ldc2, которая записывает в стек long или double и использует один байт индекса, не существует.
Инструкция ldc2_w может быть использована для записи в стек значений типа double только принадлежащий множеству значений с плавающей точкой (см. §2.3.2), поскольку величина double в константном пуле (см. §4.4.5) также принадлежит этому множеству. |
ldiv | ldiv |
Операция | Делит два значения типа long |
Формат |
|
Формы | ldiv= 109 (0x6d) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу long. Значения считываются с вершины стека операндов. Результат также принадлежит типу long и равен значение1 / значение2. После вычисления результат записывается в стек операндов.
Результат целочисленного деления округляется по направлению к нулю. Это значит, частное целочисленного деления n / d это число q, максимальное из всех, удовлетворяющих неравенству |d · q| ≤ |n|. Кроме того q положительно, когда |n| ≥ |d| и при этом n и d имеют одинаковый знак и q отрицательно, когда |n| ≥ |d| и при этом n и d имеют разные знаки. Существует один специальный случай, который не подходит под описанные выше правила: если делимое – это отрицательное целое, максимальное по модулю для типа long, а делитель равен -1, то происходит переполнение и результат равен делимому. Несмотря на переполнение, в этом случае исключение не выбрасывается. |
Исключения времени выполнения | Если делитель целочисленного деления есть 0, то ldiv генерирует исключение ArithmeticException. |
lload | lload |
Операция | Загружает значение типа long из локальной переменной в стек |
Формат |
|
Формы | lload= 22 (0x16) |
Стек операндов | ...→
..., значение |
Описание | Индекс является беззнаковым байтом. Индекс и величина индекс+1 должны принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Локальная переменная с заданным индексом должна содержать величину типа long. Значение локальной переменной, с заданным индексом, записывается в стек операндов. |
Примечания | Инструкция lload может быть использована совместно с инструкцией wide, когда необходимо задать двухбайтовый беззнаковый индекс локальной переменной. |
lload_<n> | lload_<n> |
Операция | Загружает значение типа long из локальной переменной в стек |
Формат |
|
Формы | lload_0= 30 (0x1e)
lload_1= 31 (0x1f) lload_2= 32 (0x20) lload_3= 33 (0x21) |
Стек операндов | ...→
..., значение |
Описание | И <n> и величина <n>+1 должны принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Локальная переменная с индексом <n> должна содержать величину типа long. Значение локальной переменной с индексом <n>, записывается в стек операндов. |
Примечания | Каждая из инструкции lload_<n> выполняет то же, что и lload с явным индексом <n> за исключением того, что операнд <n> задан не явно. |
lmul | lmul |
Операция | Умножает два значения типа long |
Формат |
|
Формы | lmul= 105 (0x69) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу long. Значения считываются с вершины стека операндов. Результат также принадлежит типу long и равен значение1 * значение2. После вычисления результат записывается в стек операндов.
Результат умножения – это младшие 64 бита истинного математического результата, представленного в двоичном дополнительном формате в типе long. Если происходит переполнение, то знак результата может не совпадать со знаком истинного математического результата. Несмотря на то, что переполнение возможно, исключение инструкцией lmul не выбрасывается. |
lneg | lneg |
Операция | Инвертирует значение типа long |
Формат |
|
Формы | lneg= 117 (0x75) |
Стек операндов | ..., значение →
..., результат |
Описание | Значение должно принадлежать типу long. Оно считывается со стека операндов. Результат принадлежит типу long и является арифметическим отрицанием значения. Результат записывается в стек операндов.
Для величин, принадлежащих типу long, отрицание – это тоже, что и вычитание из нуля. Поскольку виртуальная машина Java использует для целых чисел представление в двоичном дополнительном коде, а это представление не симметрично, то отрицание максимального по модулю отрицательного числа типа long есть это же число. В этом случае происходит переполнение, однако, несмотря на это исключение не генерируется. Для всех целых чисел x принадлежащих типу long, -x равно (~x) + 1. |
lookupswitch | lookupswitch |
Операция | Выполняет переход, если ключ в стеке совпадает с ключом в таблице переходов |
Формат |
|
Формы | lookupswitch= 171 (0xab) |
Стек операндов | ..., ключ →
... |
Описание | Инструкция lookupswitch является инструкцией с переменной длинной. Непосредственно за байт-кодом инструкции lookupswitch следуют байты выравнивающего смещения. Их число может меняться от одного до трёх, таким образом, чтобы адрес байта_смещения_по_умолчанию1 был кратен четырём, если считать с начала текущего метода (под началом текущего метода подразумевается адрес байт-кода первой инструкции метода). Сразу за байтами выравнивающего смещения следует набор пар знаковых 32-х битных значений: смещение_по_умолчанию, пара_значение-смещение и затем другие 32-х битные пары значение-смещение. Каждое из их этих знаковых 32-х битных значений формируется из четырёх беззнаковых байтов следующим образом: (байт1<<24) | (байт2<<16) | (байт3<<8) | байт4.
Значения таблицы пар значение-смещение должны быть расположены в порядке возрастания значений. Ключ должен принадлежать типу int. Он считывается из стека операндов. Затем ключ сравнивается со значением. Если ключ равен одному из значений, тогда целевой адрес вычисляется путём сложения соответствующего смещения и адреса байт-кода инструкции lookupswitch. Если ключ не соответствует ни одному из значений, целевой адрес вычисляется путём сложения смещения_по_умолчанию и адреса байт-кода инструкции lookupswitch. Выполнение инструкций продолжается с целевого адреса. Целевой адрес, вычисленный путём сложения смещения из каждой пары_значение-смещение с адресом инструкции lookupswitch, должен находиться в пределах метода, в котором расположена инструкция lookupswitch. |
Примечания | Пары_значение-смещение расположены в порядке возрастания значений, для ускорения поиска. В этом случае скорость поиска будет выше, чем линейная. |
lor | lor |
Операция | Булево «ИЛИ» над значениями типа long |
Формат |
|
Формы | lor= 129 (0x81) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу long. Они считываются из стека операндов. Результат также принадлежит типу long и представляет собой побитовое "или" над значением1 и значением2. Затем результат записывается в стек операндов. |
lrem | lrem |
Операция | Остаток от деления значений типа long |
Формат |
|
Формы | lrem= 113 (0x71) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу long. Они считываются из стека операндов. Результат также принадлежит типу long и представляет собой значение1 - (значение1 / значение2) * значение2. Затем результат записывается в стек операндов.
Результат инструкции lrem это величина такая, что (a/b)*b + (a%b) равна a. Это равенство справедливо даже в специальных случаях, когда делимое есть отрицательное целое, максимальное по модулю, а делитель есть -1 (при этом остаток есть 0). Из равенства следует также, что результат операции отрицателен, если делимое отрицательно и положителен, если делимое положительно. Более того, результат всегда меньше чем делитель. |
Исключения времени выполнения | Если делитель равен нулю, то инструкция lrem генерирует ArithmeticException. |
lreturn | lreturn |
Операция | Возвращает значение типа long из метода |
Формат |
|
Формы | lreturn= 173 (0xad) |
Стек операндов | ..., значение →
[пусто] |
Описание | Текущий метод должен возвращать величину типа long. Значение должно принадлежать long. Если текущий метод объявлен с ключевым словом synchronized, то при входе в метод монитор захватывается первоначально (либо повторно, если уже был захвачен до того), а при выходе освобождается, как при выполнении инструкции monitorexit для текущего потока. Если в ходе выполнения метода не было исключений, значение считывается из стека операндов текущего фрейма (см. §2.6) Затем значение записывается в стек операндов фрейма, принадлежащего вызывающему методу. Все остальные значения стека операндов текущего фрейма теряются.
Затем интерпретатор передаёт управление вызывающему методу, делая текущим соответствующий фрейм. |
Исключения времени выполнения | Если реализация виртуальной машины Java не поддерживает правила структурных блокировок описанные в §2.11.10, тогда если текущий метод объявлен как synchronized и текущий поток не является владельцем монитора, захваченного при входе в метод, то при вызове lreturn будет выброшено исключение IllegalMonitorStateException. Это может произойти, если synchronized-метод содержит инструкцию monitorexit, а инструкция monitorenter по объекту синхронизации отсутствует.
С другой стороны, если реализация виртуальной машины Java поддерживает правила структурных блокировок описанные в §2.11.10, и во время выполнения текущего метода нарушено первое из этих правил, то при вызове lreturn будет выброшено исключение IllegalMonitorStateException. |
lshl | lshl |
Операция | Сдвигает влево значение типа long |
Формат |
|
Формы | lshl= 121 (0x79) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу long. Они считываются из стека операндов. Результат также принадлежит типу long и представляет собой значение1 сдвинутое влево на s позиций, где s – это младшие 6 битов значения2. Затем результат записывается в стек операндов. |
Примечания | Операция сдвига влево эквивалентна (даже в случае переполнения) умножению исходного значения на 2 в степени s. Количество бит, на которое нужно сдвинуть значение, всегда находится в пределах от 0 до 63 включительно, как если бы до сдвига над значением2 было выполнено логическое «И» с маской 0x3f. |
lshr | lshr |
Операция | Арифметический сдвиг вправо значения типа long |
Формат |
|
Формы | lshr= 123 (0x7b) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу long. Они считываются из стека операндов. Результат также принадлежит типу long и представляет собой значение1 сдвинутое вправо на s позиций, где s – это младшие 6 битов значения2. Затем результат записывается в стек операндов. |
Примечания | Операция сдвига вправо возвращает значение равное ⌊значение1/ 2s⌋, где s - это значение2 & 0x3f. Если значение1 не отрицательно, то сдвиг эквивалентен целочисленному делению значения1 на 2 в степени s с отбрасыванием дробной части результата. Количество бит, на которое нужно сдвинуть значение, всегда находится в пределах от 0 до 63 включительно, как если бы до сдвига над значением2 было выполнено логическое «И» с маской 0x3f. |
lstore | lstore |
Операция | Считывает из стека значение типа long и записывает в локальную переменную |
Формат |
|
Формы | lstore= 55 (0x37) |
Стек операндов | ..., значение→
... |
Описание | Индекс является беззнаковым байтом. Индекс и величина индекс+1 должны принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Значение на вершине стека операндов должно принадлежать типу long. Оно считывается из стека операндов. В локальные переменные с индексами индекс и индекс+1 записывается значение. |
Примечания | Инструкция lstore может быть использована совместно с инструкцией wide, когда необходимо задать двухбайтовый беззнаковый индекс локальной переменной. |
lstore_<n> | lstore_<n> |
Операция | Считывает из стека значение типа long и записывает в локальную переменную |
Формат |
|
Формы | lstore_0= 63 (0x3f)
lstore_1= 64 (0x40) lstore_2= 65 (0x41) lstore_3= 66 (0x42) |
Стек операндов | ..., значение→
... |
Описание | И <n> и величина <n>+1 должны принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Значение на вершине стека операндов должно принадлежать типу long. Оно считывается из стека операндов. В локальные переменные с индексами <n> и <n> +1 записывается значение. |
Примечания | Каждая из инструкции lstore_<n> выполняет то же, что и lstore с явным индексом <n> за исключением того, что операнд <n> задан не явно. |
lsub | lsub |
Операция | Вычитает два значения типа long |
Формат |
|
Формы | lsub= 101 (0x65) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу long. Они считываются с вершины стек операндов. Результат типа long есть значение1 - значение2. Результат записывается в стек операндов.
Для целочисленного вычитания выражение a-b дает такой же результат, что и a+(-b). Для значений типа long вычитание из нуля есть то же самое, что и отрицание числа. Результат вычитания - это младшие 64 бита результата точного вычитания, представленные в двоичном дополнительном коде. Если происходит переполнение, то знак результата может отличаться от знака математической разности двух значений. Не смотря на то, что при выполнении инструкции lsub может произойти переполнение, инструкция lsub никогда не приводит к исключению времени выполнения. |
lushr | lushr |
Операция | Логический (беззнаковый) сдвиг вправо значения типа long |
Формат |
|
Формы | lushr= 125 (0x7d) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу long. Они считываются из стека операндов. Результат также принадлежит типу long и представляет собой значение1 сдвинутое вправо на s позиций с заполнением нулями освободившихся позиций, где s – это младшие 6 битов значения2. Затем результат записывается в стек операндов. |
Примечания | Если значение1 положительно и s равно значение2 & 0x3f, то результат сдвига равен значение1 >> s; если значение1 отрицательно, то результат равен выражению (значение1 >> s) + (2L <<~s). Добавление слагаемого (2L <<~s) эквивалентно тому, что знаковый бит при сдвиге будет заменён нулём. Количество бит, на которое нужно сдвинуть значение, всегда находится в пределах от 0 до 63 включительно. |
lxor | lxor |
Операция | Булево исключающее «ИЛИ» над значениями типа long |
Формат |
|
Формы | lxor= 131 (0x83) |
Стек операндов | ..., значение1, значение2 →
..., результат |
Описание | И значение1 и значение2 должны принадлежать типу long. Они считываются из стека операндов. Результат также принадлежит типу long и представляет собой результат операции «исключающее ИЛИ» над значением1 и значением2. Затем результат записывается в стек операндов. |
monitorenter | monitorenter |
Операция | Захватывает монитор объекта |
Формат |
|
Формы | monitorenter= 194 (0xc2) |
Стек операндов | ..., ссылка на объект →
... |
Описание | Ссылка на объект должна принадлежать типу reference.
Каждый объект поставлен в соответствие некоторому монитору. Монитор захвачен тогда и только тогда, когда у него есть владелец. Поток, который выполняет инструкцию monitorenter, пытается захватить монитор, связанный со ссылкой на объект следующим образом:
|
Исключения времени выполнения | Если ссылка на объект равна null, monitorenter генерирует
NullPointerException. |
Примечания | Инструкция monitorenter может быть использована совместно с одной или несколькими инструкциями monitorexit для реализации synchronized-блока языка программирования Java. Инструкции monitorenter и monitorexit не используются при имплементации synchronized-методов, хотя их можно использовать для эквивалентной реализации блокировок. При вызове synchronized-метода виртуальная машина Java неявно выполняет захват монитора и неявно освобождает монитор при выполнении инструкции возврата из synchronized-метода. Этот неявный захват и освобождение монитора эквивалентен выполнению инструкций monitorenter и monitorexit.
Поддержка связи монитора и объекта может быть выполнена различными способами, описание которых выходит за рамки данной спецификации. Например, монитор может создаваться и уничтожаться одновременно с созданием и уничтожением объекта. С другой стороны, монитор может создаваться при первой попытке потока захватить его и уничтожаться после того, как поток освободил его, и нет других потоков, пытающихся захватить его. Конструкции синхронизации языка программирования Java требуют поддержки и других операций с монитором, кроме захвата и освобождения. Эти операции включают в себя ожидание на мониторе (Object.wait) и уведомление других потоков, ждущих на мониторе, о том, что монитор свободен (Object.notifyAll и Object.notify). Эти операции поддерживаются в стандартном пакете java.lang, поставляемом с виртуальной машиной Java. Среди инструкций виртуальной машины Java отсутствует явная поддержка указанных выше операций. |
monitorexit | monitorexit |
Операция | Освобождает монитор объекта |
Формат |
|
Формы | monitorexit = 195 (0xc3) |
Стек операндов | ..., ссылка на объект →
... |
Описание | Ссылка на объект должна принадлежать типу reference.
Поток, который выполняет инструкцию monitorexit должен быть владельцем монитора, поставленного в соответствие объекту, на который ссылается ссылка на объект. Поток уменьшает счётчик монитора, связанного с объектом. Если значение счётчика станет равным нулю, то поток, освободивший монитор больше не является его владельцем. Другие потоки, для которых доступ к монитору был заблокирован, теперь могут попытаться захватить монитор. |
Исключения времени выполнения | Если ссылка на объект равна null, monitorexit генерирует
NullPointerException. Если поток, который выполняет инструкцию monitorexit не является владельцем монитора поставленного в соответствие объекту, на который ссылается ссылка на объект, то monitorexit генерирует исключение IllegalMonitorStateException. Если реализация виртуальной машины Java поддерживает правила структурной блокировки (см. §2.11.10), и второе из этих правил нарушено, то monitorexit генерирует IllegalMonitorStateException. |
Примечания | Инструкция monitorexit может быть использована совместно с одной или несколькими инструкциями monitorenter для реализации synchronized-блока языка программирования Java. Инструкции monitorenter и monitorexit не используются при имплементации synchronized-методов, хотя их можно использовать для эквивалентной реализации блокировок.
Виртуальная машина Java по-разному обрабатывает исключения, которые возникают в synchronized -блоках и synchronized -методах:
|
multianewarray | multianewarray |
Операция | Создаёт новый многомерный массив |
Формат |
|
Формы | multianewarray= 197 (0xc5) |
Стек операндов | ..., число_элементов_измерения1, [число_элементов_измерения2,...] →
..., ссылка на массив |
Описание | Число измерений - беззнаковый байт, принимающий значение большее либо равное единице. Он представляет собой количество размерностей массива, который необходимо создать. Стек операндов должен содержать значение каждой размерности. Каждое такое значение есть число_элементов_измерения. Оно должно принадлежать типу int и быть не отрицательным.
Все значения количества элементов измерения считываются из стека операндов. Беззнаковые байт_индекса1 и байт_индекса2 используются для построения индекса массива в константном пуле времени выполнения текущего класса (см. §2.6). Значение индекса определяется как (байт_индекса1 << 8)|(байт_индекса2). Элемент константного пула, на который указывает построенный индекс, должен быть ссылкой на класс, массив или интерфейс. Обозначенный класс, массив или интерфейс разрешается (см. §5.4.3.1). Разрешенный элемент должен быть массивом с размерностью большей или равной числу_измерений. В куче выделяется память для многомерного массива, элементы которого также являются массивами. Если число_элементов_измерения равно нулю, то память для подразмерностей не выделяется. Компоненты массива первой размерности инициализируются ссылками на подмассив второго измерения и так далее. Компоненты последнего измерения массива инициализируются значениями по умолчанию для соответствующих типов данных (см. §2.3, §2.4). Ссылка на массив с типом reference записывается в стек операндов. |
Исключения связывания | Во время разрешения символьной ссылки на класс, массив или интерфейс, может быть создано любое исключение, описанное в (§5.4.3.1).
Если текущий класс не имеет доступа к типу, который объявлен в качестве типа элементов массива, то multianewarray генерирует IllegalAccessError. |
Исключения времени выполнения | Если любое число_элементов_измерения в стеке операндов меньше нуля, то multianewarray генерирует NegativeArraySizeException. |
Примечания | Для создания одномерного массива более эффективным является использование инструкций newarray или anewarray.
Массив, в константном пуле, на которые ссылается инструкция multianewarray с помощью байтов_индекса фактически может иметь большую размерность, чем операнд число_измерений. В этом случае создаются только указанные в качестве операндов измерения. |
new | new |
Операция | Создаёт новый объект |
Формат |
|
Формы | new= 187 (0xbb) |
Стек операндов | ...→
..., ссылка на объект |
Описание | Беззнаковые байт_индекса1 и байт_индекса2 используются для построения индекса массива в константном пуле времени выполнения текущего класса (см. §2.6). Значение индекса определяется как (байт_индекса1 << 8)|(байт_индекса2). Элемент константного пула, на который указывает построенный индекс, должен быть символьной ссылкой на класс, или интерфейс. Массив или интерфейс разрешается (см. §5.4.3.1) и в результате разрешения должен быть получен класс. Память для нового экземпляра указанного класса берётся из кучи, а поля экземпляра инициализируются соответствующими значениями по умолчанию (см. 2.3, §2.4). Ссылка на экземпляр с типом reference записывается в стек операндов.
При успешном разрешении класса, он инициализируется (см. §5.5), если до этого он ещё не был инициализирован. |
Исключения связывания | Во время разрешения символьной ссылки на класс, массив или интерфейс, может быть создано любое исключение, описанное в (§5.4.3.1).
Если в ходе разрешения символьной ссылки будет получен абстрактный класс или интерфейс, инструкция new генерирует исключение InstantiationError. |
Исключения времени выполнения | Если в ходе выполнения инструкции new происходит инициализация класса, new может генерировать любую из ошибок (наследник класса Error), подробно описанных в JLS §15.9.4. |
Примечания | Инструкция new не до конца выполняет создание нового экземпляра класса. Создание экземпляра будет не завершено до тех пор пока не вызван инициализирующий метод (см. §2.9) экземпляра. |
newarray | newarray |
Операция | Создаёт новый массив |
Формат |
|
Формы | newarray= 188 (0xbc) |
Стек операндов | ..., количество элементов →
..., ссылка на массив |
Описание | Количество элементов должно принадлежать типу int. Оно считывается из стека операндов.
Код_типа_компонентов_массива может принимать одно из следующих значений: Таблица. Коды типов массива
В куче создаётся новый новый массив, чьи компоненты имеют тип, соответствующий указанному коду. Ссылка на массив типа reference записывается в стек операндов. Каждый элемент массива инициализируется значением по умолчанию (см. §2.3, §2.4) для своего собственного типа. |
Исключения времени выполнения | Если количество элементов меньше нуля, то инструкция newarray генерирует исключение NegativeArraySizeException. |
Примечания | В реализации виртуальной машины Java компании Oracle, массивы с типом boolean (код_типа_элементов_массива есть T_BOOLEAN) хранятся в виде последовательности байт (один байт хранит одно значение типа boolean). Доступ к таким массивам осуществляется посредством инструкций baload и bastore, которые также используются для работы массивами типа byte. Другие реализации виртуальной машины могут использовать упакованные массивы типа boolean, однако доступ к элементам таких массивов также должен выполняться с помощью инструкций baload и bastore. |
nop | nop |
Операция | Не делает ничего |
Формат |
|
Формы | nop= 0 (0x0) |
Стек операндов | Нет
Без изменений |
Описание | Не делает ничего |
pop | pop |
Операция | Считывает операнд с вершины стека |
Формат |
|
Формы | pop= 87 (0x57) |
Стек операндов | ..., значение→
... |
Описание | Считывает значения из стека операндов.
Инструкция pop только если тип значения принадлежит категории 1 (см. §2.11.1) |
pop2 | pop2 |
Операция | Считывает один или два операнда с вершины стека |
Формат |
|
Формы | pop2= 88 (0x58) |
Стек операндов | Форма 1:
... где значение1, значение2 – это значения из категории 1 вычислимых типов (см. §2.11.1)
... где значение – это значение из категории 1 вычислимых типов (см. §2.11.1) |
Описание | Считывает одно или два значения из стека операндов. |
putfield | putfield |
Операция | Записывает значение в поле объекта |
Формат |
|
Формы | putfield= 181 (0xb5) |
Стек операндов | ..., ссылка на объект, значение →
... |
Описание | Беззнаковые байт_индекса1 и байт_индекса2 используются для построения индекса массива в константном пуле времени выполнения текущего класса (см. §2.6). Значение индекса определяется как (байт_индекса1 << 8)|(байт_индекса2). Элемент константного пула, на который указывает построенный индекс, должен быть символьной ссылкой на поле класса (см. §5.1), Элемент константного пула содержит имя поля, дескриптор поля и символьную ссылку на класс, которому принадлежит поле. Ссылка на объект не должна ссылаться на массив. Если поле класса объявлено как protected (см. §4.6) и оно принадлежит предку текущего класса и не объявлено в том же пакете что и текущий класс (§5.3), то в этом случае ссылка на объект должна указывать либо на текущий класс, либо на его предка.
Поле разрешается (см. §5.4.3.2). Тип значения, которое записывает инструкция putfield, должен быть совместим с типом в дескрипторе поля (см. §4.3.2). Если тип поля в дескрипторе равен boolean, byte, char, short или int, то значение должно принадлежать типу int. Если тип поля в дескрипторе равен float, long или double, то значение должно быть float, long или double соответственно. Если тип поля в дескрипторе это ссылочный тип, то тип значения должен быть совместим с данным типом для операции присваивания (JLS §5.2). Если поле final, то оно должно быть объявлено в текущем классе, а инструкция putfield должна находиться в инициализирующем методе (<init>) текущего класса (см. §2.9) Значение и ссылка на объект считываются из стека операндов. Ссылка на объект должна принадлежать типу reference. Значение проходит ряд преобразований (§2.8.3), затем преобразованное значение` записывается в поле экземпляра, на который указывает ссылка на объект. |
Исключения связывания | Во время разрешения символьной ссылки на поле может быть выброшено любое исключение, описанное в (§5.4.3.2).
Если разрешённое поле статическое (static), то инструкция putfield генерирует IncompatibleClassChangeError. Если поле final, то оно должно быть объявлено в текущем классе, а инструкция должна находиться в инициализирующем методе (<init>) текущего класса. В противно случае будет выброшен исключение IllegalAccessError. |
Исключения времени выполнения | Если ссылка на объект равна null, то инструкция putfield генерирует NullPointerException. |
putstatic | putstatic |
Операция | Записывает значение в статическое поле объекта |
Формат |
|
Формы | putstatic= 179 (0xb3) |
Стек операндов | ..., значение→
... |
Описание | Беззнаковые байт_индекса1 и байт_индекса2 используются для построения индекса массива в константном пуле времени выполнения текущего класса (см. §2.6). Значение индекса определяется как (байт_индекса1 << 8)|(байт_индекса2). Элемент константного пула, на который указывает построенный индекс, должен быть символьной ссылкой на поле класса (см. §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, то оно должно быть объявлено в текущем классе, а инструкция putstatic должна находиться в инициализирующем методе (<init>) текущего класса (см. §2.9) Значение считывается из стека операндов и проходит ряд преобразований (§2.8.3), затем преобразованное значение` записывается в поле класса. |
Исключения связывания | Во время разрешения символьной ссылки на поле класса или интерфейса может быть выброшено любое исключение, описанное в (§5.4.3.2).
Если разрешенное поле не статическое (static), то инструкция putstatic генерирует IncompatibleClassChangeError. Если поле final, то оно должно быть объявлено в текущем классе, а инструкция должна находиться в инициализирующем методе (<init>) текущего класса. В противно случае будет выброшен исключение IllegalAccessError. |
Исключения времени выполнения | Если вызов инструкции putstatic приводит к инициализации класса или интерфейса, то putstatic может вызвать ошибку, более подробно описанную в разделе §5.5. |
Примечания | Инструкция putstatic может быть использована для установки значений поля интерфейса только при инициализации поля. Поля интерфейса инициализируются только один раз, когда вычисляется выражение интерфейсного поля при инициализации самого интерфейса (см. §5.5, JLS §9.3.1) |
ret | ret |
Операция | Возвращает управление из подпрограммы |
Формат |
|
Формы | ret= 169 (0xa9) |
Стек операндов | Без изменений |
Описание | Индекс - это беззнаковый байт от 0 до 255 включительно. Локальная переменная в текущем фрейме (см. §2.6) с заданным индексом должна содержать величину типа returnAddress. Содержимое локальной переменной записывается в регистр pc виртуальной машины Java, и выполнение инструкций продолжается с нового адреса. |
Примечания | Обратите внимание, что инструкция jsr записывает адрес возврата в стек операндов, инструкция ret считывает его из локальной переменной. Эта асимметрия выполнена намеренно.
В реализации компилятора языка программирования Java компании Oracle до версии Java SE 6 инструкция ret использовалась совместно с jsr и jsr_w для имплементации блока finally (см. §3.13, §4.10.2.5). Не следует путать инструкцию ret и return. Инструкция return возвращает управление из метода без передачи параметров вызвавшему методу. Инструкция ret может быть использована совместно с wide для доступа к локальным переменным, имеющим двухбайтовый индекс. |
return | return |
Операция | Возврат из void метода |
Формат |
|
Формы | return= 177 (0xb1) |
Стек операндов | ...→
[пусто] |
Описание | Текущий метод должен иметь тип возвращаемого значения void. Если текущий метод объявлен как synchronized, то при входе в метод происходит захват (или повторный захват) монитора и, возможно, освобождение монитора (если перед выполнением инструкции return счётчик захвата монитора был равен единице - прим. перев.). Если в ходе выполнения метода исключений выброшено не было, то все значения стека операндов текущего фрейма теряются.
Затем интерпретатор возвращает управление вызывающему методу, делая активным соответствующий фрейм. |
Исключения времени выполнения | Если реализация виртуальной машины Java не поддерживает правила структурной блокировки (см. §2.11.10), тогда происходит следующее: если текущий метод объявлен как synchronized и текущий поток не владеет монитором, который захватывается при входе в метод, то return генерирует IllegalMonitorStateException. Это происходит, например, когда метод, объявленный как synchronized, содержит инструкцию monitorexit, но не содержит monitorenter для объекта, которому принадлежит метод.
Если реализация виртуальной машины Java поддерживает правила структурной блокировки (см. §2.11.10), и первое из этих правил нарушено, то return генерирует IllegalMonitorStateException. |
saload | saload |
Операция | Записывает значение типа short из массива в стек |
Формат |
|
Формы | saload= 53 (0x35) |
Стек операндов | ..., ссылка на массив, индекс →
..., значение |
Описание | Ссылка на массив должна быть типа reference и ссылаться на массив, чьи компоненты значения типа short. Индекс должен принадлежать типу int. Как ссылка на массив, так и индекс считываются из стека операндов. Значение типа short считывается из элемента массива с соответствующим индексом и записывается в стек операндов. |
Исключения времени выполнения | Если ссылка на массив равна null, то saload генерирует NullPointerException. В противном случае, если индекс вне границ массива, генерируется исключение ArrayIndexOutOfBoundsException. |
sastore | sastore |
Операция | Записывает значение типа short из стека в массив |
Формат |
|
Формы | sastore= 86 (0x56) |
Стек операндов | ..., ссылка на массив, индекс, значение→
... |
Описание | Ссылка на массив должна быть типа reference и ссылаться на массив, чьи компоненты значения типа short. Индекс должен принадлежать типу int, значение должно принадлежать типу short. Ссылка на массив, индекс и значение считываются из стека операндов. Затем значение сохраняется в массиве с заданным индексом. |
Исключения времени выполнения | Если ссылка на массив равна null, то sastore генерирует NullPointerException. В противном случае, если индекс вне границ массива, генерируется исключение ArrayIndexOutOfBoundsException. |
sipush | sipush |
Операция | Записывает в стек значение типа short |
Формат |
|
Формы | sipush= 17 (0x11) |
Стек операндов | ...→
..., значение |
Описание | Промежуточные байт1 и байт2 преобразуются в значение типа short: (байт1 << 8) | байт2. Затем полученное значение расширяется с учётом знака до int, которое и записывается в стек операндов. |
swap | swap |
Операция | Меняет местами два операнда на вершине стека |
Формат |
|
Формы | swap= 95 (0x5f) |
Стек операндов | ..., значение2, значение1 →
..., значение1, значение2 |
Описание | Меняет местами два значение на вершине стека операндов.
Инструкция swap должна использоваться только, если тип значения1 и значения2 принадлежит первой категории вычислимых типов (см. §2.11.1) |
Примечания | Виртуальная машина Java не имеет инструкции для перемены местами значений, чей тип принадлежит категории 2 вычислимых типов. |
tableswitch | tableswitch |
Операция | Выполняет переход в зависимости от индекса смещения в стеке |
Формат |
|
Формы | tableswitch= 170 (0xaa) |
Стек операндов | ..., индекс →
... |
Описание | Инструкция tableswitch является инструкцией с переменной длинной. Непосредственно за байт-кодом инструкции tableswitch следуют байты выравнивающего смещения. Их число может меняться от одного до трёх, таким образом, чтобы адрес байта_смещения_по_умолчанию1 был кратен четырём, если считать с начала текущего метода (под началом текущего метода подразумевается адрес байт-кода первой инструкции метода). Сразу за байтами выравнивающего смещения следует три 32-х битных значения: смещение_по_умолчанию, нижняя_граница, верхняя_граница. Затем следует набор 32-х битных смещений переходов, количество которых равно верхняя_граница - нижняя_граница + 1. Значение нижней_границы должно быть меньше либо равно верхней_границы. Набор 32-х битных смещений представляет собой таблицу переходов, где в качестве базы для смещения используется адрес инструкции tableswitch. Каждое из их этих знаковых 32-х битных значений формируется из четырёх беззнаковых байтов следующим образом: (байт1<<24) | (байт2<<16) | (байт3<<8) | байт4.
Индекс типа int считывается с вершины стека операндов. Если индекс меньше нижней_границы или больше верхней_границы, то целевой адрес перехода вычисляется путём сложения смещения по умолчанию и адреса инструкции tableswitch. Если индекс лежит в пределах нижней_границы и верхней_границы, то целевой адрес перехода вычисляется путём сложения найденного смещения и адреса инструкции tableswitch. Выполнение инструкций продолжается с целевого адреса. Целевой адрес, вычисленный путём сложения смещения переходов из таблицы переходов или смещения по умолчанию с адресом инструкции tableswitch, должен находиться в пределах метода, в котором расположена инструкция tableswitch. |
wide | wide |
Операция | Расширяет значение индекса локальной переменной за счёт дополнительных байтов |
Формат 1 |
|
где <код операции> принимает значение iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore, или ret |
Формат 2 |
|
Формы | wide= 196 (0xc4) |
Стек операндов | Такой же, как и у модифицируемой команды |
Описание | Инструкция wide изменяет поведение другой инструкции. Инструкция wide может быть использована в двух формах, в зависимости от расширяемой команды. Первая форма инструкции wide изменяет поведение следующих инструкций: iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore и ret. Вторая форма применима только к инструкции iinc.
В любом случае за байт-кодом инструкцией wide следует байт-код модифицируемой инструкции. Вне зависимости от формы два беззнаковых байта байт_индекса1 и байт_индекса2, следующие за байт-кодом модифицируемой инструкции преобразуются в 16-ти битный беззнаковый индекс локальной переменной текущего фрейма (§2.6), где значение индекса равно (байт_индекса1 << 8) | байт_индекса2. Там, где инструкция wide модифицирует поведение инструкций lload, dload, lstore и dstore, индекс локальной переменной, следующий за вычисленным ранее (индекс + 1), должен также указывать на локальную переменную. Два беззнаковых байта байт_константы1 и байт_константы2, следуют непосредственно за байтом_индекса1 и байтом_индекса2 во второй форме wide. Эти байты также преобразуются в знаковую 16-ти битную константу по формуле (байт_константы1 << 8) | байт_константы2. «Расширенная» инструкция выполняет то же, что и стандартная, за исключением того, что использует более широкий индекс, а в случае второй формы – ещё и слагаемое более широкого диапазона. |
Примечания | Хотя мы и говорим «изменяет поведение другой инструкции» инструкция wide по сути использует байт код другой инструкции в качестве своего собственного операнда, в процессе выполнения изменяя нормальное поведение исходной команды. В случае расширения инструкции iinc изменяется и формат команды: один из операндов смещается относительно позиции байт-кода iinc (имеется в виду второй байт константы инкремента – прим. перев.). Расширенная инструкция никогда не должна выполняться без инструкции wide: её адрес не может быть целевым адресом переход при передаче управления. |