Список инструкций JVM с детальным описанием формата и действий, которые они выполняют

Материал из JavaCogito
Перейти к навигации Перейти к поиску

Список инструкций JVM с детальным описанием формата и действий, которые они выполняют - перевод на русский язык главы Спецификации виртуальной машины Java.


Перевод: Саянкин А.А.

aaload aaload


Операция Загружает ссылку из массива


Формат
aaload


Формы aaload = 50 (0x32)


Стек операндов ..., ссылка на массив, индекс
..., значение


Описание Значение ссылки на массив должно быть типа reference и должно ссылаться на массив, чьи компоненты также принадлежат типу reference. Значение индекса должно быть типа int. Как ссылка на массив так и индекс считываются из стека операндов. Значение типа reference считывается из элемента массива с индексом индекс и записывается в стек операндов.


Исключения времени выполнения Если значение ссылки на массив равно null, то инструкция aaload генерирует исключение NullPointerException.





aastore aastore


Операция Сохраняет ссылку (reference) из стека в массив


Формат
aastore


Формы aastore= 83 (0x53)


Стек операндов ..., ссылка на массив, индекс, значение

...


Описание Значение ссылки на массив должно быть типа reference и должно ссылаться на массив, чьи компоненты также принадлежат типу reference. Значение индекса должно быть типа int, значение должно быть типа reference. Значение, ссылка на массив и индекс считываются из стека операндов. Значение типа reference сохраняется в элементе массива с индексом индекс.

Во время выполнения тип значения должен быть совместим с типом компонентов массива, на который ссылается ссылка на массив.

Присваивание ссылочного типа S (источник) типу T (приёмник) допустимо тогда и только тогда:

  • Если S - это класс, тогда:
    • Если T – это класс, то S должно быть такого же класса, как и T либо S должно быть наследником T;
    • Если T – это интерфейс, то S должно реализовывать этот интерфейс;
  • Если S - это интерфейс, тогда:
    • Если T – это класс, тогда T должно быть типа Object.
    • Если T – это интерфейс, то S должно быть тем же интерфейсом или интерфейсом-предком S.
  • Если S – это массив (назовём его SC[], что значит массив с компонентами типа SC), тогда:
    • Если T – это класс, тогда T должен быть Object.
    • Если T – это интерфейс, тогда T должно быть одним из интерфейсов, которые реализует массив (см. JLS §4.10.3).
    • Если T – массив TC[], что значит массив с компонентами типа TC, тогда одно из следующих утверждений должно быть истинным:
      • TC и SC принадлежат одному примитивному типу.
      • TC и SC ссылочные типы и SC можно присвоить TC.


Исключения времени выполнения Если ссылка на массив равна null, то инструкция aaload генерирует исключение NullPointerException.

В противном случае, если индекс вне границ массива, на который ссылается ссылка на массив, то aastore генерирует исключение ArrayIndexOutOfBoundsException.





aconst_null aconst_null


Операция Записывает в стек null


Формат
aconst_null


Формы aconst_null= 1 (0x1)


Стек операндов ... →

..., null


Описание Записывает в стек операндов ссылку на null объект.


Примечания Виртуальная машина Java не определяет конкретного значения для null.





aload aload


Операция Загружает ссылку из локальной переменной в стек


Формат
aload
индекс


Формы aload = 25 (0x19)


Стек операндов ..., →

..., ссылка на объект


Описание Индекс представляет собой беззнаковый байт, который определяет локальную переменную текущего фрейма (§2.6). Локальная переменная с указанным индексом должна содержать значение типа reference. Ссылка на объект из локальной переменной записывается в стек операндов.


Примечания Инструкция aload не может быть использована для записи в стек операндов значений типа returnAddress из локальной переменной. Эта асимметрия с инструкцией astore сделана намеренно.

Инструкция aload может быть использована с инструкцией wide для доступа к локальным переменным, имеющим двухбайтовый индекс.





aload_<n> 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
байт_индекса1
байт_индекса2


Формы 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


Формы 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


Формы arraylength= 190 (0xbe)


Стек операндов ..., ссылка на массив

..., длина массива


Описание Ссылка на массив должна принадлежать типу reference. Она считывается из стека операндов. Определяется длина массива по указанной ссылке. Эта длина массива записывается в стек операндов как значение типа int.


Исключения времени выполнения Если ссылка на массив равна null, arraylength генерирует NullPointerException.





astore 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_<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


Формы 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


Формы 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


Формы 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
байт


Формы bipush= 16 (0x10)


Стек операндов ..., →

..., значение


Описание С помощью знакового расширения значение байта преобразуется к типу int и записывается в стек операндов.





caload caload


Операция Загружает значение типа char из массива в стек


Формат
caload


Формы caload= 52 (0x34)


Стек операндов ..., ссылка на массив, индекс

..., значение


Описание Ссылка на массив должна принадлежать типу reference и ссылаться на массив, чьи компоненты являются типами char. Индекс должен принадлежать типу int. Как ссылка на массив, так и индекс считываются из стека операндов. Значение считывается из элемента массива с заданным индексом, расширяется без учёта знака до типа int и записывается вершину стека операндов.


Исключения времени выполнения Если ссылка на массив равна null, то caload генерирует NullPointerException.

Если индекс вне границ массива, то caload генерирует ArrayIndexOutOfBoundsException.





castore castore


Операция Загружает значение типа char в массив


Формат
castore


Формы castore= 85 (0x55)


Стек операндов ..., ссылка на массив, индекс, значение

...


Описание Ссылка на массив должна принадлежать типу reference и ссылаться на массив, чьи компоненты являются типами char. Индекс должен принадлежать типу int. Как ссылка на массив, индекс так и значение считываются из стека операндов. Значение, принадлежащее типу char, урезается до типа byte и записывается в массив, в элемент с заданным индексом.


Исключения времени выполнения Если ссылка на массив равна null, castore генерирует NullPointerException.

Если индекс вне границ массива, то castore генерирует ArrayIndexOutOfBoundsException.





checkcast checkcast


Операция Проверяет, принадлежит ли объект заданному типу


Формат
checkcast
байт_индекса1
байт_индекса2


Формы checkcast= 192 (0xc0)


Стек операндов ..., ссылка на объект

..., ссылка на объект


Описание Ссылка на объект должна принадлежать типу reference. Беззнаковые байт_индекса1 и байт_индекса2 используются для построения индекса массива в константном пуле времени выполнения текущего класса (см. §2.6). Значение индекса определяется как (байт_индекса1 << 8)|(байт_индекса2). Элемент константного пула, на который указывает построенный индекс, должен быть ссылкой на класс, массив или интерфейс.

Если ссылка на объект равна null, то содержимое стека операндов не меняется.

В противном случае класс, массив или интерфейс разрешается (см. §5.4.3.1). Если ссылка на объект может быть преобразована к разрешённому ранее классу, массиву или интерфейсу, то стек операндов не меняется. В противном случае инструкция checkcast генерирует исключение ClassCastException.

Если ссылка на объект не равна null, то используются следующие правила для разрешения типов: если S - класс, на который ссылается ссылка на объект, а T – разрешаемый класс, массив или интерфейс, то checkcast проверяет следующее:

  • Если S - это класс, тогда:
    • Если T – это класс, то S должно быть такого же класса, как и T либо S должно быть наследником T;
    • Если T – это интерфейс, то S должно реализовывать этот интерфейс;
  • Если S - это интерфейс, тогда:
    • Если T – это класс, тогда T должно быть типа Object.
    • Если T – это интерфейс, то S должно быть тем же интерфейсом или интерфейсом-предком S.
  • Если S – это массив (назовём его SC[], что значит массив с компонентами типа SC), тогда:
    • Если T – это класс, тогда T должен быть Object.
    • Если T – это интерфейс, тогда T должно быть одним из интерфейсов, которые реализует массив (см. JLS §4.10.3).
    • Если T – массив TC[], что значит массив с компонентами типа TC, тогда одно из следующих утверждений должно быть истинным:
      • TC и SC принадлежат одному примитивному типу.
      • TC и SC ссылочные типы и SC можно присвоить TC.


Исключения связывания Во время разрешения символьной ссылки на класс, массив или интерфейс, может быть создано любое исключение, описанное в (§5.4.3.1).


Исключения времени выполнения Если ссылка на объект не может быть преобразована к разрешённому классу, массиву или интерфейсу checkcast генерирует ClassCastException.


Примечания Инструкция checkcast очень похожа на инструкцию instanceof. Они отличаются друг от друга реакцией на null (checkcast генерирует исключение, instanceof записывает код результата в стек) и влиянием на стек операндов.





d2f d2f


Операция Преобразует double к float


Формат
d2f


Формы 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


Формы d2i= 142 (0x8e)


Стек операндов ..., значение

..., результат


Описание Значение на вершине стека операндов должно быть типа double. Оно считывается из стека операндов и подвергается набору преобразований (см. §2.8.3). Затем новое значение преобразуется к типу int. Результат записывается в стек операндов.
  • Если новое значение не-число NaN, результат преобразования int 0.
  • В противном случае, если новое значение не бесконечность, оно округляется к целочисленному V согласно IEEE 754 (округление в направлении нуля). Если это целое число представимо в типе int, то Vрезультат преобразования.
  • Если число V не представимо в типе int (оно слишком мало или является отрицательной бесконечностью) то результатом будет наименьшее число представимое в диапазоне int. Либо V не представимо в типе int, поскольку оно слишком велико или является положительной бесконечностью, то результатом будет наибольшее число представимое в диапазоне int.


Примечания Инструкция d2i выполняет сужающее преобразование примитивных типов, поэтому может преобразуемая величина быть потеряна полностью либо потеряна точность представления.





d2l d2l


Операция Преобразует double к long


Формат
d2l


Формы d2l= 143 (0x8f)


Стек операндов ..., значение

..., результат


Описание Значение на вершине стека операндов должно быть типа double. Оно считывается из стека операндов и подвергается набору преобразований (см. §2.8.3). Затем новое значение преобразуется к типу long. Результат записывается в стек операндов.
  • Если новое значение не-число NaN, результат преобразования long 0.
  • В противном случае, если новое значение не бесконечность, оно округляется к целочисленному V согласно IEEE 754 (округление в направлении нуля). Если это целое число представимо в типе int, то Vрезультат преобразования.
  • Если число V не представимо в типе long (оно слишком мало или является отрицательной бесконечностью) то результатом будет наименьшее число представимое в диапазоне long. Либо V не представимо в типе long, поскольку оно слишком велико или является положительной бесконечностью, то результатом будет наибольшее число представимое в диапазоне long.


Примечания Инструкция d2l выполняет сужающее преобразование примитивных типов, поэтому может преобразуемая величина быть потеряна полностью либо потеряна точность представления.





dadd dadd


Операция Складывает два числа типа double


Формат
dadd


Формы dadd= 99 (0x63)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу double. Значения считываются из стека операндов, проходят преобразования (см. §2.8.3) становясь значением1` и значением2`. Результат типа double равен сумме значение1` + значение2`. Результат записывается в стек операндов.

Суммирование производится согласно правилам арифметики IEEE: Если либо значение1` либо значение2` есть не-число NaN, то результат есть NaN.

  • Сумма двух бесконечностей противоположных знаков есть NaN.
  • Сумма двух бесконечностей одинаковых знаков есть бесконечность того же знака.
  • Сумма бесконечности и конечного числа есть бесконечность.
  • Сумма двух нулей противоположных знаков есть положительный ноль.
  • Сумма двух нулей одинаковых знаков есть ноль того же знака.
  • Сумма двух не нулевых конечных значений одинаковой величины есть положительный ноль.
  • В оставшихся случаях, когда ни один из операндов не бесконечность, не ноль и не NaN и значения имеют один знак или имеют разную величину, сумма вычисляется и округляется к ближайшему представимому значению согласно правилам округления IEEE 754. Если результат слишком велик, чтобы быть представленным как double, мы говорим, что произошло переполнение. В этом случае результат есть бесконечность соответствующего знака. Если результат слишком мал, чтобы быть представленным как double, мы говорим, что произошла потеря точности. В этом случае результат есть ноль соответствующего знака.

Инструкция dadd не генерирует исключение, если происходит переполнение или потеря точности.





daload daload


Операция Загружает значение типа double из массива в стек


Формат
daload


Формы daload= 49 (0x31)


Стек операндов ..., ссылка на массив, индекс

..., значение


Описание Ссылка на массив должна быть типа reference и ссылаться на массив, чьи компоненты значения типа double. Индекс должен принадлежать типу int. Как ссылка на массив, так и индекс считываются из стека операндов. Значение типа double считывается из элемента массива с соответствующим индексом и записывается в стек операндов.


Исключения времени выполнения Если ссылка на массив равна null, то daload генерирует NullPointerException. В противном случае, если индекс вне границ массива, генерируется исключение ArrayIndexOutOfBoundsException.





dastore dastore


Операция Загружает значение типа double в массив


Формат
dastore


Формы dastore= 82 (0x52)


Стек операндов ..., ссылка на массив, индекс, значение

...


Описание Ссылка на массив должна быть типа reference и ссылаться на массив, чьи компоненты значения типа double. Индекс должен принадлежать типу int, значение должно принадлежать типу double. Ссылка на массив, индекс и значение считываются из стека операндов. Над значением проводится набор преобразований (см. §2.8.3), в результате которых значение` сохраняется в массиве с заданным индексом.


Исключения времени выполнения Если ссылка на массив равна null, то dastore генерирует NullPointerException. В противном случае, если индекс вне границ массива, генерируется исключение ArrayIndexOutOfBoundsException.





dcmp<op> dcmp<op>


Операция Сравнивает два значения типа double


Формат
dcmp<op>


Формы dcmpg= 152 (0x98)

dcmpl= 151 (0x97)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу double. Значения считываются из стека операндов и подвергаются набору преобразований (см. §2.8.3) и заменяются на значение1` и значение2`. Сравнение значений с плавающей точкой производится следующим образом:
  • Если значение1` больше чем значение2`, то в стек операндов записывается единица с типом int.
  • В противном случае, если значение1` равно значению2`, то в стек операндов записывается ноль с типом int.
  • В противном случае, если значение1` меньше чем значение2`, то в стек операндов записывается минус единица с типом int.
  • В противном случае, по крайней мере, одно значение (либо значение1`, либо значение2`) есть не-число NaN. В этом случае инструкция dcmpg записывает 1 с типом int в стек операндов, а инструкция dcmpl записывает -1 с типом int в стек операндов.

Сравнение чисел с плавающей точкой выполняется согласно требованиям стандарта IEEE754. Все значения, отличные от не-числа NaN упорядочены, причём отрицательная бесконечность меньше чем все числа, а положительная бесконечность больше чем все числа. Положительный и отрицательный ноль считаются равными.


Примечания Инструкции dcmpg и dcmpl отличаются только своим поведением при сравнении не-чисел NaN. Поскольку NaN не упорядочено, любое сравнения не-числа NaN и значения типа double не определено, в случае, когда один либо оба операнда не-числа NaN. С помощью инструкций dcmpg и dcmpl любое сравнения чисел типа double может быть скомпилировано так, чтобы выдавать результат, совпадающий и при сравнение обычных чисел и при сравнении не-чисел NaN. Более подробную информацию см. в §3.5.





dconst_<d> dconst_<d>


Операция Записывает константу типа double в стек


Формат
dconst_<d>


Формы dconst_0= 14 (0xe)

dconst_1= 15 (0xf)


Стек операндов ...→

... <d>


Описание Записывает в стек операндов константу <d> (0.0 или 1.0) типа double.





ddiv ddiv


Операция Делит два значения типа double


Формат
ddiv


Формы ddiv= 111 (0x6f)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу double. Значения считываются из стека операндов и подвергаются набору преобразований (см. §2.8.3) и заменяются на значение1` и значение2`. Результат – это число типа double равное значение1`/ значение2`. Затем результат записывается в стек операндов.

Результат инструкции ddiv вычисляется согласно правилам арифметики стандарта IEEE:

  • Если либо значение1` либо значение2` есть не-число NaN, то результат есть NaN.
  • Если ни значение1` ни значение2` не являются не-числами NaN, то знак результата деления положительный, если делимое и делитель имеют один знак и отрицательный в противном случае.
  • Деление бесконечности на бесконечность даёт не-число NaN.
  • Деление бесконечности на конечное значение даёт бесконечность, знак которой определён по правилу, описанному выше.
  • Деление конечного значения на бесконечность даёт знаковый ноль, знак которого определён по правилу, описанному выше.
  • Деление ноль на ноль даёт не-число NaN; деление ноля на конечное значение даёт знаковый ноль, знак которого определён по правилу, описанному выше.
  • Деление не нулевого конечного значения на ноль даёт бесконечность, знак которой определён по правилу, описанному выше.
  • В оставшихся случаях, когда операнды не бесконечность, не ноль и не NaN частное вычисляется и округляется к ближайшему double, используя режим округления к ближайшему стандарта IEEE 754. Если величина слишком велика, чтобы быть представленной в диапазоне типа double, говорят, что произошло переполнение. В этом случае результатом является бесконечность соответствующего знака. Если величина слишком мала, чтобы быть представленной в диапазоне типа double, говорят, что произошла потеря точности. В этом случае результатом является ноль соответствующего знака.

Несмотря на переполнение, потерю точности, деление на ноль инструкция ddiv никогда не генерирует исключение времени выполнения.





dload dload


Операция Загружает значение типа double из локальной переменной в стек


Формат
dload
индекс


Формы dload= 24 (0x18)


Стек операндов ...→

..., значение


Описание Индекс является беззнаковым байтом. Индекс и величина индекс+1 должны принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Локальная переменная с заданным индексом должна содержать величину типа double. Значение локальной переменной, с заданным индексом, записывается в стек операндов.


Примечания Инструкция dload может быть использована совместно с инструкцией wide, когда необходимо задать двухбайтовый беззнаковый индекс локальной переменной.





dload_<n> dload_<n>


Операция Загружает значение типа double из локальной переменной в стек


Формат
dload_<n>


Формы dload_0= 38 (0x26)

dload_1= 39 (0x27)

dload_2= 40 (0x28)

dload_3= 41 (0x29)


Стек операндов ... →

..., значение


Описание И <n> и величина <n>+1 должны принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Локальная переменная с индексом <n> должна содержать величину типа double. Значение локальной переменной с индексом <n>, записывается в стек операндов.


Примечания Каждая из инструкции dload_<n> выполняет то же, что и dload с явным индексом <n> за исключением того, что операнд <n> задан не явно.





dmul dmul


Операция Умножает два значения типа double


Формат
dmul


Формы dmul= 107 (0x6b)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу double. Значения считываются из стека операндов и подвергаются набору преобразований (см. §2.8.3) и заменяются на значение1` и значение2`. Результат – это число типа double равное значение1`* значение2`. Затем результат записывается в стек операндов.

Результат инструкции dmul вычисляется согласно правилам арифметики стандарта IEEE:

  • Если либо значение1` либо значение2` есть не-число NaN, то результат есть NaN.
  • Если ни значение1` ни значение2` не являются не-числами NaN, то знак результата умножения положительный, если операнды имеют один знак и отрицательный в противном случае.
  • Умножение бесконечности на ноль даёт не-число NaN.
  • Умножение бесконечности на конечное значение даёт бесконечность, знак которой определён по правилу, описанному выше.
  • В оставшихся случаях, когда операнды не бесконечность, не ноль и не NaN произведение вычисляется и округляется к ближайшему double, используя режим округления к ближайшему стандарта IEEE 754. Если величина слишком велика, чтобы быть представленной в диапазоне типа double, говорят, что произошло переполнение. В этом случае результатом является бесконечность соответствующего знака. Если величина слишком мала, чтобы быть представленной в диапазоне типа double, говорят, что произошла потеря точности. В этом случае результатом является ноль соответствующего знака.

Несмотря на переполнение, потерю точности dmul никогда не генерирует исключение времени выполнения.





dneg dneg


Операция Инвертирует значение типа double


Формат
dneg


Формы dneg= 119 (0x77)


Стек операндов ..., значение

..., результат


Описание Значение должно принадлежать типу double. Оно считывается из стека операндов, и подвергаются набору преобразований (см. §2.8.3), а затем заменяется значением`. Результат – это число типа double равное арифметическому отрицанию значения`. Затем результат записывается в стек операндов.

Для значений типа double отрицание не есть то же самое, что и вычитание из нуля. Если x это +0.0, то 0.0 - x равно +0.0, но -x равно -0.0. Унарный минус лишь инвертирует знак числа типа double.

Особые случаи:

  • Если операнд есть не-число NaN, то результат также NaN (поскольку у NaN нет знака).
  • Если операнд – бесконечность, то результат – бесконечность противоположного знака.
  • Если операнд – ноль, то результат – ноль противоположного знака.





drem drem


Операция Остаток от деления двух чисел типа double


Формат
drem


Формы 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 вычисляется согласно следующим правилам:

  • Если либо значение1` либо значение2` есть не-число NaN, то результат есть NaN.
  • Если ни значение1` ни значение2` не являются не-числами NaN, то знак результата совпадает со знаком делимого.
  • Если делимое есть бесконечность или делитель есть ноль, либо оба числа есть нули, то результат – не-число NaN.
  • Если делимое есть конечное значение, а делитель – бесконечность, то результат (остаток от деления) равен делимому.
  • Если делимое есть ноль, а делитель – конечное значение, то результат (остаток от деления) равен делимому.
  • В оставшихся случаях, когда операнды не бесконечность, не ноль и не NaN остаток от деления с плавающей точкой делимого значения1` на делитель значение2` определяется следующим отношением: результат = значение1` - (значение2` * q), где q – целое число, имеющее знак минус в случае, если значение1` / значение2` отрицательно и знак плюс, если значение1` / значение2` положительно. Величина коэффициента q равно наибольшему целому не превосходящему частного от деления значения1` на значение2`.

Несмотря на деление на ноль инструкция drem никогда не генерирует исключение времени выполнения. Переполнение и потеря точности не могут произойти для этой инструкции.


Примечания Остаток от деления согласно спецификации IEEE 754 может быть вычислен с помощью метода Math.IEEEremainder.





dreturn dreturn


Операция Возвращает значение типа double из метода


Формат
dreturn


Формы 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
индекс


Формы dstore= 57 (0x39)


Стек операндов ..., значение

...


Описание Индекс является беззнаковым байтом. Индекс и величина индекс+1 должны принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Значение на вершине стека операндов должно принадлежать типу double. Оно считывается из стека операндов, и подвергаются набору преобразований (см. §2.8.3), а затем заменяется значением`. В локальные переменные с индексами индекс и индекс+1 записывается значение`.


Примечания Инструкция dstore может быть использована совместно с инструкцией wide, когда необходимо задать двухбайтовый беззнаковый индекс локальной переменной.





dstore_<n> dstore_<n>


Операция Считывает значение типа double из стека и сохраняет в локальной переменной


Формат
dstore_<n>


Формы dstore_0= 71 (0x47)

dstore_1= 72 (0x48)

dstore_2= 73 (0x49)

dstore_3= 74 (0x4a)


Стек операндов ..., значение

...


Описание И <n> и величина <n>+1 должны принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Значение на вершине стека операндов должно принадлежать типу double. Оно считывается из стека операндов, и подвергаются набору преобразований (см. §2.8.3), а затем заменяется значением`. В локальные переменные с индексами <n> и <n> +1 записывается значение`.


Примечания Каждая из инструкции dstore_<n> выполняет то же, что и dstore с явным индексом <n> за исключением того, что операнд <n> задан не явно.





dsub dsub


Операция Вычитает два значения типа double


Формат
dsub


Формы 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


Формы dup= 89 (0x59)


Стек операндов ..., значение

..., значение, значение


Описание Копирует значение на вершине стека операндов и записывает копию на вершину стека.

Инструкция dup не должна использоваться, если значение не принадлежит категории 1 вычислимых типов (см. §2.11.1)





dup_x1 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


Формы 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


Формы dup2= 92 (0x5c)


Стек операндов Форма 1:


... значение2, значение1

..., значение2, значение1, значение2, значение1

где значение1, значение2 принадлежат категории 1 вычислимых типов (см. §2.11.1)


Форма 2:


..., значение

..., значение, значение

где значение принадлежит категории 2 вычислимых типов (см. §2.11.1)


Описание Копирует одно или два значения на вершине стека операндов и записывает копию (одно или два значения) в стек.





dup2_x1 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


Формы dup2_x2= 94 (0x5e)


Стек операндов Форма 1:


..., значение4, значение3, значение2, значение1

..., значение2, значение1, значение4, значение3, значение2, значение1

где значение1, значение2, значение3 и значение4 принадлежат категории 1 вычислимых типов (см. §2.11.1)


Форма 2:


..., значение3, значение2, значение1

..., значение1, значение3, значение2, значение1

где значение1 принадлежит категории 2 вычислимых типов, а значение2 и значение3 принадлежат категории 1 (см. §2.11.1)


Форма 3:


..., значение3, значение2, значение1

..., значение2, значение1, значение3, значение2, значение1

где значение1 и значение2 принадлежат категории 1 вычислимых типов, а значение3 принадлежит категории 1 (см. §2.11.1)


Форма 4:


..., значение2, значение1

..., значение1, значение2, значение1

где значение1 и значение3 принадлежат категории 2 вычислимых типов (см. §2.11.1)


Описание Копирует одно или два значения на вершине стека операндов и записывает копию (одно или два значения) в стек.





f2d f2d


Операция Преобразует значение типа float к double


Формат
f2d


Формы 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


Формы f2i= 139 (0x8b)


Стек операндов ..., значение

..., результат


Описание Значение на вершине стека операндов должно быть типа float. Оно считывается из стека операндов и подвергается набору преобразований (см. §2.8.3). Затем новое значение преобразуется к типу int. Результат записывается в стек операндов.
  • Если новое значение не-число NaN, результат преобразования int 0.
  • В противном случае, если новое значение не бесконечность, оно округляется к целочисленному V согласно IEEE 754 (округление в направлении нуля). Если это целое число представимо в типе int, то Vрезультат преобразования.
  • Если число V не представимо в типе int (оно слишком мало или является отрицательной бесконечностью) то результатом будет наименьшее число представимое в диапазоне int. Либо V не представимо в типе int, поскольку оно слишком велико или является положительной бесконечностью, то результатом будет наибольшее число представимое в диапазоне int.


Примечания Инструкция f2i выполняет сужающее преобразование примитивных типов, поэтому преобразуемая величина может быть потеряна полностью либо потеряна точность представления.





f2l f2l


Операция Преобразует значение типа float к long


Формат
f2l


Формы f2l= 140 (0x8c)


Стек операндов ..., значение

..., результат


Описание Значение на вершине стека операндов должно быть типа float. Оно считывается из стека операндов и подвергается набору преобразований (см. §2.8.3). Затем новое значение преобразуется к типу long. Результат записывается в стек операндов.
  • Если новое значение не-число NaN, результат преобразования long 0.
  • В противном случае, если новое значение не бесконечность, оно округляется к целочисленному V согласно IEEE 754 (округление в направлении нуля). Если это целое число представимо в типе long, то Vрезультат преобразования.
  • Если число V не представимо в типе long (оно слишком мало или является отрицательной бесконечностью) то результатом будет наименьшее число представимое в диапазоне long. Либо V не представимо в типе long, поскольку оно слишком велико или является положительной бесконечностью, то результатом будет наибольшее число представимое в диапазоне long.


Примечания Инструкция f2l выполняет сужающее преобразование примитивных типов, поэтому преобразуемая величина может быть потеряна полностью либо потеряна точность представления.





fadd fadd


Операция Складывает два значения типа float


Формат
fadd


Формы fadd= 98 (0x62)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу float. Значения считываются из стека операндов, проходят преобразования (см. §2.8.3) становясь значением1` и значением2`. Результат типа float равен сумме значение1` + значение2`. Результат записывается в стек операндов.

Суммирование производится согласно правилам арифметики IEEE:

  • Если либо значение1` либо значение2` есть не-число NaN, то результат есть NaN.
  • Сумма двух бесконечностей противоположных знаков есть NaN.
  • Сумма двух бесконечностей одинаковых знаков есть бесконечность того же знака.
  • Сумма бесконечности и конечного числа есть бесконечность.
  • Сумма двух нулей противоположных знаков есть положительный ноль.
  • Сумма двух нулей одинаковых знаков есть ноль того же знака.
  • Сумма двух не нулевых конечных значений одинаковой величины есть положительный ноль.
  • В оставшихся случаях, когда ни один из операндов не бесконечность, не ноль и не NaN и значения имеют один знак или имеют разную величину, сумма вычисляется и округляется к ближайшему представимому значению согласно правилам округления IEEE 754. Если результат слишком велик, чтобы быть представленным как float, мы говорим, что произошло переполнение. В этом случае результат есть бесконечность соответствующего знака. Если результат слишком мал, чтобы быть представленным как float, мы говорим, что произошла потеря точности. В этом случае результат есть ноль соответствующего знака.

Инструкция fadd не генерирует исключение, если происходит переполнение или потеря точности.





faload faload


Операция Записывает в стек значение из массива типа float


Формат
faload


Формы faload= 48 (0x30)


Стек операндов ..., ссылка на массив, индекс

..., значение


Описание Ссылка на массив должна быть типа reference и ссылаться на массив, чьи компоненты значения типа float. Индекс должен принадлежать типу int. Как ссылка на массив, так и индекс считываются из стека операндов. Значение типа float считывается из элемента массива с соответствующим индексом и записывается в стек операндов.


Исключения времени выполнения Если ссылка на массив равна null, то faload генерирует NullPointerException. В противном случае, если индекс вне границ массива, генерируется исключение ArrayIndexOutOfBoundsException.





fastore fastore


Операция Записывает значение типа float в массив


Формат
fastore


Формы fastore= 81 (0x51)


Стек операндов ..., ссылка на массив, индекс, значение

...


Описание Ссылка на массив должна быть типа reference и ссылаться на массив, чьи компоненты значения типа float. Индекс должен принадлежать типу int, значение должно принадлежать типу float. Ссылка на массив, индекс и значение считываются из стека операндов. Над значением проводится набор преобразований (см. §2.8.3), в результате которых значение` сохраняется в массиве с заданным индексом.


Исключения времени выполнения Если ссылка на массив равна null, то fastore генерирует NullPointerException. В противном случае, если индекс вне границ массива, генерируется исключение ArrayIndexOutOfBoundsException.





fcmp<op> fcmp<op>


Операция Сравнивает два значение типа float


Формат
fcmp<op>


Формы fcmpg= 150 (0x96)

fcmpl= 149 (0x95)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу float. Значения считываются из стека операндов и подвергаются набору преобразований (см. §2.8.3) и заменяются на значение1` и значение2`.

Сравнение значений с плавающей точкой производится следующим образом:

  • Если значение1` больше чем значение2`, то в стек операндов записывается единица с типом int.
  • В противном случае, если значение1` равно значению2`, то в стек операндов записывается ноль с типом int.
  • В противном случае, если значение1` меньше чем значение2`, то в стек операндов записывается минус единица с типом int.
  • В противном случае, по крайней мере, одно значение (либо значение1`, либо значение2`) есть не-число NaN. В этом случае инструкция fcmpg записывает 1 с типом int в стек операндов, а инструкция fcmpl записывает -1 с типом int в стек операндов.

Сравнение чисел с плавающей точкой выполняется согласно требованиям стандарта IEEE754. Все значения, отличные от не-числа NaN упорядочены, причем отрицательная бесконечность меньше чем все числа, а положительная бесконечность больше чем все числа. Положительный и отрицательный ноль считаются равными.


Примечания Инструкции fcmpg и fcmpl отличаются только своим поведением при сравнении не-чисел NaN. Поскольку NaN не упорядочено, любое сравнения не-числа NaN и значения типа float не определено, в случае, когда один либо оба операнда не-числа NaN. С помощью инструкций fcmpg и fcmpl любое сравнения чисел типа float может быть скомпилировано так, чтобы выдавать результат, совпадающий и при сравнение обычных чисел и при сравнении не-чисел NaN. Более подробную информацию см. в §3.5.





fconst_<f> fconst_<f>


Операция Записывает в стек константу типа float


Формат
fconst_<f>


Формы 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


Формы fdiv= 110 (0x6e)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу float. Значения считываются из стека операндов и подвергаются набору преобразований (см. §2.8.3) и заменяются на значение1` и значение2`.

Результат – это число типа float равное значение1`/ значение2`. Затем результат записывается в стек операндов.

Результат инструкции fdiv вычисляется согласно правилам арифметики стандарта IEEE:

  • Если либо значение1` либо значение2` есть не-число NaN, то результат есть NaN.
  • Если ни значение1` ни значение2` не являются не-числами NaN, то знак результата деления положительный, если делимое и делитель имеют один знак и отрицательный в противном случае.
  • Деление бесконечности на бесконечность даёт не-число NaN.
  • Деление бесконечности на конечное значение даёт бесконечность, знак которой определён по правилу, описанному выше.
  • Деление конечного значения на бесконечность даёт знаковый ноль, знак которого определён по правилу, описанному выше.
  • Деление ноль на ноль даёт не-число NaN; деление ноля на конечное значение даёт знаковый ноль, знак которого определён по правилу, описанному выше.
  • Деление не нулевого конечного значения на ноль дает бесконечность, знак которой определён по правилу, описанному выше.
  • В оставшихся случаях, когда операнды не бесконечность, не ноль и не NaN частное вычисляется и округляется к ближайшему float, используя режим округления к ближайшему стандарта IEEE 754. Если величина слишком велика, чтобы быть представленной в диапазоне типа float, говорят, что произошло переполнение. В этом случае результатом является бесконечность соответствующего знака. Если величина слишком мала, чтобы быть представленной в диапазоне типа float, говорят, что произошла потеря точности. В этом случае результатом является ноль соответствующего знака.

Несмотря на переполнение, потерю точности, деление на ноль инструкция fdiv никогда не генерирует исключение времени выполнения.





fload fload


Операция Записывает в стек значение типа float из локальной переменной


Формат
fload
индекс


Формы fload= 23 (0x17)


Стек операндов ...→

..., значение


Описание Индекс является беззнаковым байтом. Индекс должен принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Локальная переменная с заданным индексом должна содержать величину типа float. Значение локальной переменной, с заданным индексом, записывается в стек операндов.


Примечания Инструкция fload может быть использована совместно с инструкцией wide, когда необходимо задать двухбайтовый беззнаковый индекс локальной переменной.





fload_<n> fload_<n>


Операция Записывает в стек значение типа float из локальной переменной


Формат
fload_<n>


Формы fload_0= 34 (0x22)

fload_1= 35 (0x23)

fload_2= 36 (0x24)

fload_3= 37 (0x25)


Стек операндов ...→

..., значение


Описание <n> должно принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Локальная переменная <n> должна содержать величину типа float. Значение локальной переменной <n>, записывается в стек операндов.


Примечания Каждая из инструкции fload_<n> выполняет то же, что и fload с явным индексом <n> за исключением того, что операнд <n> задан не явно.





fmul fmul


Операция Умножает два значения типа float


Формат
fmul


Формы fmul= 106 (0x6a)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу float. Значения считываются из стека операндов и подвергаются набору преобразований (см. §2.8.3) и заменяются на значение1` и значение2`.

Результат – это число типа float равное значение1`* значение2`. Затем результат записывается в стек операндов.

Результат инструкции fmul вычисляется согласно правилам арифметики стандарта IEEE:

  • Если либо значение1` либо значение2` есть не-число NaN, то результат есть NaN.
  • Если ни значение1` ни значение2` не являются не-числами NaN, то знак результата умножения положительный, если операнды имеют один знак и отрицательный в противном случае.
  • Умножение бесконечности на ноль даёт не-число NaN.
  • Умножение бесконечности на конечное значение даёт бесконечность, знак которой определён по правилу, описанному выше.
  • В оставшихся случаях, когда операнды не бесконечность, не ноль и не NaN произведение вычисляется и округляется к ближайшему float, используя режим округления к ближайшему стандарта IEEE 754. Если величина слишком велика, чтобы быть представленной в диапазоне типа float, говорят, что произошло переполнение. В этом случае результатом является бесконечность соответствующего знака. Если величина слишком мала, чтобы быть представленной в диапазоне типа float, говорят, что произошла потеря точности. В этом случае результатом является ноль соответствующего знака.

Несмотря на переполнение, потерю точности fmul никогда не генерирует исключение времени выполнения.





fneg fneg


Операция Инвертирует значение типа float


Формат
fneg


Формы fneg= 118 (0x76)


Стек операндов ..., значение

..., результат


Описание Значение должно принадлежать типу float. Оно считывается из стека операндов, и подвергаются набору преобразований (см. §2.8.3), а затем заменяется значением`. Результат – это число типа float равное арифметическому отрицанию значения`. Затем результат записывается в стек операндов.

Для значений типа float отрицание не есть то же самое, что и вычитание из нуля. Если x это +0.0, то 0.0 - x равно +0.0, но -x равно -0.0. Унарный минус лишь инвертирует знак числа типа float.

Особые случаи:

  • Если операнд есть не-число NaN, то результат также NaN (поскольку у NaN нет знака).
  • Если операнд – бесконечность, то результат – бесконечность противоположного знака.
  • Если операнд – ноль, то результат – ноль противоположного знака.





frem frem


Операция Остаток от деления двух значений типа float


Формат
frem


Формы 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 вычисляется согласно следующим правилам:

  • Если либо значение1` либо значение2` есть не-число NaN, то результат есть NaN.
  • Если ни значение1` ни значение2` не являются не-числами NaN, то знак результата совпадает со знаком делимого.
  • Если делимое есть бесконечность или делитель есть ноль, либо оба числа есть нули, то результат – не-число NaN.
  • Если делимое есть конечное значение, а делитель – бесконечность, то результат (остаток от деления) равен делимому.
  • Если делимое есть ноль, а делитель – конечное значение, то результат (остаток от деления) равен делимому.
  • В оставшихся случаях, когда операнды не бесконечность, не ноль и не NaN остаток от деления с плавающей точкой делимого значения1` на делитель значение2` определяется следующим отношением: результат = значение1` - (значение2` * q), где q – целое число, имеющее знак минус в случае, если значение1` / значение2` отрицательно и знак плюс, если значение1` / значение2` положительно. Величина коэффициента q равно наибольшему целому не превосходящему частного от деления значения1` на значение2`.

Несмотря на деление на ноль инструкция frem никогда не генерирует исключение времени выполнения. Переполнение и потеря точности не могут произойти для этой инструкции.


Примечания Остаток от деления согласно спецификации IEEE 754 может быть вычислен с помощью метода Math.IEEEremainder.





freturn freturn


Операция Возвращает значение float из метода


Формат
freturn


Формы 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
индекс


Формы fstore= 56 (0x38)


Стек операндов ..., значение

...


Описание Индекс является беззнаковым байтом и должен принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Значение на вершине стека операндов должно принадлежать типу float. Оно считывается из стека операндов, и подвергаются набору преобразований (см. §2.8.3), а затем заменяется значением`. В локальную переменную с индексом индекс записывается значение`.


Примечания Инструкция fstore может быть использована совместно с инструкцией wide, когда необходимо задать двухбайтовый беззнаковый индекс локальной переменной.





fstore_<n> fstore_<n>


Операция Загружает значение типа float из стека в локальную переменную


Формат
fstore_<n>


Формы fstore_0= 67 (0x43)

fstore_1= 68 (0x44)

fstore_2= 69 (0x45)

fstore_3= 70 (0x46)


Стек операндов ..., значение

...


Описание <n> должно принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Значение на вершине стека операндов должно принадлежать типу float. Оно считывается из стека операндов, и подвергаются набору преобразований (см. §2.8.3), а затем заменяется значением`. В локальную переменную с индексом <n> записывается значение`.


Примечания Каждая из инструкции fstore_<n> выполняет то же, что и fstore с явным индексом <n> за исключением того, что операнд <n> задан не явно.





fsub fsub


Операция Вычитает два значения типа float


Формат
fsub


Формы 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
байт_индекса1
байт_индекса2


Формы 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
байт_индекса1
байт_индекса1


Формы 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
байт_адреса1
байт_адреса2


Формы goto= 167 (0xa7)


Стек операндов Без изменений


Описание Беззнаковые байт_адреса1 и байт_адреса2 используются для построения 16-битового знакового смещения перехода (байт_адреса1 << 8) | байт_адреса2. Смещение выполняется относительно индекса инструкции goto, управление передаётся команде, находящейся по рассчитанному смещению. Смещение должно находиться в пределах метода, содержащего инструкцию goto.





goto_w goto_w


Операция Безусловный переход (широкий индекс)


Формат
goto_w
байт_адреса1
байт_адреса2
байт_адреса3
байт_адреса4


Формы 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


Формы i2b= 145 (0x91)


Стек операндов ..., значение

..., результат


Описание Значение на вершине стека операндов должно принадлежать типу int. Оно считывается с вершины стека операндов, обрезается до размера byte, а затем расширяется с учётом знака снова к типу int. Результат расширения записывается в стек операндов.


Примечания Инструкция i2b выполняет сужающее преобразование примитивных типов (см. JLS §5.1.3). Это может привести к потере исходного значения. Знак результата может также отличатся от знака исходного значения.





i2c i2c


Операция Преобразует значение типа int к char


Формат
i2c


Формы i2c= 146 (0x92)


Стек операндов ..., значение

..., результат


Описание Значение на вершине стека операндов должно принадлежать типу int. Оно считывается с вершины стека операндов, обрезается до размера char, а затем расширяется без учёта знака снова к типу int. Результат расширения записывается в стек операндов.


Примечания Инструкция i2c выполняет сужающее преобразование примитивных типов (см. JLS §5.1.3). Это может привести к потере исходного значения. Знак результата может также отличатся от знака исходного значения.





i2d i2d


Операция Преобразует значение типа int к double


Формат
i2d


Формы i2d= 135 (0x87)


Стек операндов ..., значение

..., результат


Описание Значение на вершине стека операндов должно принадлежать типу int. Оно считывается с вершины стека операндов и преобразуется к типу double. Результат записывается в стек операндов.


Примечания Инструкция i2d выполняет расширяющее преобразование примитивных типов. Поскольку все значения типа int точно представимы в типе double, то преобразование точное.





i2f i2f


Операция Преобразует значение типа int к float


Формат
i2f


Формы i2f= 134 (0x86)


Стек операндов ..., значение

..., результат


Описание Значение на вершине стека операндов должно принадлежать типу int. Оно считывается с вершины стека операндов и преобразуется к типу double, согласно правилам округления к ближайшему стандарта IEEE 754. Результат записывается в стек операндов.


Примечания Инструкция i2d выполняет расширяющее преобразование примитивных типов (см. JLS §5.1.2), но может привести к потере точности, поскольку тип float имеет только 24 бита для хранения мантиссы значения.





i2l i2l


Операция Преобразует значение типа int к long


Формат
i2l


Формы i2l= 133 (0x85)


Стек операндов ..., значение

..., результат


Описание Значение на вершине стека операндов должно принадлежать типу int. Оно считывается с вершины стека операндов и преобразуется к типу long (путем знакового расширения). Результат записывается в стек операндов.


Примечания Инструкция i2l выполняет расширяющее преобразование примитивных типов (см. JLS §5.1.2). Поскольку все значения типа int точно представимы в типе long, то преобразование точное.





i2s i2s


Операция Преобразует значение типа int к short


Формат
i2s


Формы i2s= 147 (0x93)


Стек операндов ..., значение

..., результат


Описание Значение на вершине стека операндов должно принадлежать типу int. Оно считывается с вершины стека операндов, обрезается до размера short, а затем расширяется с учётом знака снова к типу int. Результат расширения записывается в стек операндов.


Примечания Инструкция i2s выполняет сужающее преобразование примитивных типов (см. JLS §5.1.3). Это может привести к потере исходного значения. Знак результата может также отличатся от знака исходного значения.





iadd iadd


Операция Складывает два значения типа int


Формат
iadd


Формы iadd= 96 (0x60)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу int. Они считываются с вершины стек операндов. Результат типа int есть значение1 + значение2. Результат записывается в стек операндов.

Результат сложения - это младшие 32 бита результата точного сложения, представленные в двоичном дополнительном коде. Если происходит переполнение, то знак результата может отличаться от знака математической суммы двух значений.

Не смотря на то, что при выполнении инструкции iadd может произойти переполнение, инструкция iadd никогда не приводит к исключению времени выполнения.





iaload iaload


Операция Записывает в стек значение int из массива


Формат
iaload


Формы iaload= 46 (0x2e)


Стек операндов ..., ссылка на массив, индекс

..., значение


Описание Ссылка на массив должна быть типа reference и ссылаться на массив, чьи компоненты значения типа int. Индекс должен принадлежать типу int. Как ссылка на массив, так и индекс считываются из стека операндов. Значение типа int считывается из элемента массива с соответствующим индексом и записывается в стек операндов.


Исключения времени выполнения Если ссылка на массив равна null, то iaload генерирует NullPointerException. В противном случае, если индекс вне границ массива, генерируется исключение ArrayIndexOutOfBoundsException.





iand iand


Операция Логическое «И» над значениями с типом int


Формат
iand


Формы iand= 126 (0x7e)


Стек операндов ..., значение1, значение2

...,результат


Описание И значение1 и значение2 должны принадлежать типу int. Они считываются с вершины стек операндов. Результат типа int есть логическое "И" над значением1 и значением2. Результат записывается в стек операндов.





iastore iastore


Операция Загружает значения типа int из стека в массив


Формат
iastore


Формы iastore= 79 (0x4f)


Стек операндов ..., ссылка на массив, индекс, значение

...


Описание Ссылка на массив должна быть типа reference и ссылаться на массив, чьи компоненты значения типа int. Индекс должен принадлежать типу int, значение должно принадлежать типу int. Ссылка на массив, индекс и значение считываются из стека операндов. Затем значение сохраняется в массиве с заданным индексом.


Исключения времени выполнения Если ссылка на массив равна null, то iastore генерирует NullPointerException. В противном случае, если индекс вне границ массива, генерируется исключение ArrayIndexOutOfBoundsException.





iconst_ iconst_


Операция Записывает в стек константу типа int


Формат
iconst_


Формы iconst_m1= 2 (0x2)

iconst_0= 3 (0x3)

iconst_1= 4 (0x4)

iconst_2= 5 (0x5)

iconst_3= 6 (0x6)

iconst_4= 7 (0x7)

iconst_5= 8 (0x8)


Стек операндов ..., значение

...,


Описание Записывает в стек целочисленную константу (-1, 0, 1, 2, 3, 4 или 5)


Примечания Каждая из семейства инструкций эквивалента bipush с соответствующим аргументом, за исключением того, что задано не явно.





idiv 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_acmp<cond>
байт_адреса1
байт_адреса2


Формы if_acmpeq= 165 (0xa5)

if_acmpne= 166 (0xa6)


Стек операндов ..., значение1, значение2

...


Описание И значение1 и значение2 должны принадлежать типу reference. Они оба считываются из стека операндов и сравниваются. Результат сравнения следующий:
  • if_acmpeq дает истину, если value1= value2
  • if_acmpne дает истину, если value1value2

Если сравнение дало истину, беззнаковые байт_адреса1 и байт_адреса2 используются для построения знакового 16-ти битового смещения, которое вычисляется следующим образом: (байт_адреса1 << 8) | байт_адреса2. Затем выполнение инструкций продолжается со смещения, вычисленного ранее относительно инструкции if_acmp<cond>. Целевой адрес перехода должен быть в пределах метода, содержащего if_acmp<cond>.

В противном случае (если сравнение дало ложь), выполнение инструкций продолжается непосредственно с инструкции, следующей за if_acmp<cond>.





if_icmp<cond> if_icmp<cond>


Операция Переход, если значения типа int удовлетворяют условию


Формат
if_icmp<cond>
байт_адреса1
байт_адреса2


Формы 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. Они оба считываются из стека операндов и сравниваются. Все сравнения – знаковые. Результаты сравнения вычисляются следующим образом:
  • if_icmpeq истинно тогда и только тогда, когда value1= value2
  • if_icmpne истинно тогда и только тогда, когда value1 ≠ value2
  • if_icmplt истинно тогда и только тогда, когда value1< value2
  • if_icmple истинно тогда и только тогда, когда value1 ≤ value2
  • if_icmpgt истинно тогда и только тогда, когда value1> value2
  • if_icmpge истинно тогда и только тогда, когда value1 ≥ value2

Если сравнение дало истину, беззнаковые байт_адреса1 и байт_адреса2 используются для построения знакового 16-ти битового смещения, которое вычисляется следующим образом: (байт_адреса1 << 8) | байт_адреса2. Затем выполнение инструкций продолжается со смещения, вычисленного ранее относительно инструкции if_icmp<cond>. Целевой адрес перехода должен быть в пределах метода, содержащего if_icmp<cond>.

В противном случае (если сравнение дало ложь), выполнение инструкций продолжается непосредственно с инструкции, следующей за if_icmp<cond>.





if<cond> if<cond>


Операция Переход, если сравнение значения типа int с нулем – «истина»


Формат
if<cond>
байт_адреса1
байт_адреса2


Формы ifeq= 153 (0x99)

ifne= 154 (0x9a)

iflt= 155 (0x9b)

ifge= 156 (0x9c)

ifgt= 157 (0x9d)

ifle= 158 (0x9e)


Стек операндов ..., значение

...


Описание Значение должно принадлежать типу int. Оно считывается из стека операндов и сравнивается с нулём. Все сравнения – знаковые. Результаты сравнения вычисляются следующим образом:
  • ifeq истинно тогда и только тогда, когда value = 0
  • ifne истинно тогда и только тогда, когда value ≠ 0
  • iflt истинно тогда и только тогда, когда value < 0
  • ifle истинно тогда и только тогда, когда value ≤ 0
  • ifgt истинно тогда и только тогда, когда value > 0
  • ifge истинно тогда и только тогда, когда value ≥ 0

Если сравнение дало истину, беззнаковые байт_адреса1 и байт_адреса2 используются для построения знакового 16-ти битового смещения, которое вычисляется следующим образом: (байт_адреса1 << 8) | байт_адреса2. Затем выполнение инструкций продолжается со смещения, вычисленного ранее относительно инструкции if<cond>. Целевой адрес перехода должен быть в пределах метода, содержащего if<cond>.

В противном случае (если сравнение дало ложь), выполнение инструкций продолжается непосредственно с инструкции, следующей за if<cond>.





ifnonnull ifnonnull


Операция Переход, если значение типа reference не null


Формат
ifnonnull
байт_адреса1
байт_адреса2


Формы ifnonnull= 199 (0xc7)


Стек операндов ..., значение

...


Описание Значение должно принадлежать типу reference. Оно считываются из стека операндов. Если значение не null то, беззнаковые байт_адреса1 и байт_адреса2 используются для построения знакового 16-ти битового смещения, которое вычисляется следующим образом: (байт_адреса1 << 8) | байт_адреса2. Затем выполнение инструкций продолжается со смещения, вычисленного ранее относительно инструкции ifnonnull. Целевой адрес перехода должен быть в пределах метода, содержащего ifnonnull.

В противном случае (если сравнение дало ложь), выполнение инструкций продолжается непосредственно с инструкции, следующей за ifnonnull.





ifnull ifnull


Операция Переход, если значение типа reference равно null


Формат
ifnull
байт_адреса1
байт_адреса2


Формы ifnull= 198 (0xc6)


Стек операндов ..., значение

...


Описание Значение должно принадлежать типу reference. Оно считываются из стека операндов. Если значение null то, беззнаковые байт_адреса1 и байт_адреса2 используются для построения знакового 16-ти битового смещения, которое вычисляется следующим образом: (байт_адреса1 << 8) | байт_адреса2. Затем выполнение инструкций продолжается со смещения, вычисленного ранее относительно инструкции ifnull. Целевой адрес перехода должен быть в пределах метода, содержащего ifnull.

В противном случае (если сравнение дало ложь), выполнение инструкций продолжается непосредственно с инструкции, следующей за ifnull.





iinc iinc


Операция Увеличивает локальную переменную на заданную константу


Формат
iinc
индекс
константа


Формы iinc= 132 (0x84)


Стек операндов Без изменений


Описание Индекс – это беззнаковый байт, который должен быть индексом локальной переменной текущего фрейма (см. §2.6). Константа – знаковый байт, следующий непосредственно за кодом операции. Локальная переменная с заданным индексом должна содержать значение типа int. Затем константа расширяется с учётом знака до типа int и добавляется к локальной переменной с заданным индексом.


Примечания Инструкция iinc может быть использована совместно с инструкцией wide, когда необходимо задать двухбайтовый беззнаковый индекс локальной переменной и при этом увеличить переменную на двухбайтовое знаковое значение.





iload iload


Операция Загружает значение типа int из локальной переменной в стек


Формат
iload
индекс


Формы iload= 21 (0x15)


Стек операндов ..., →

..., значение


Описание Индекс является беззнаковым байтом. Индекс должен принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Локальная переменная с заданным индексом должна содержать величину типа int. Значение локальной переменной, с заданным индексом, записывается в стек операндов.


Примечания Инструкция iload может быть использована совместно с инструкцией wide, когда необходимо задать двухбайтовый беззнаковый индекс локальной переменной.





iload_<n> iload_<n>


Операция Записывает в стек значение локальной переменной типа int


Формат
iload_<n>


Формы iload_0= 26 (0x1a)

iload_1= 27 (0x1b)

iload_2= 28 (0x1c)

iload_3= 29 (0x1d)


Стек операндов ... →

..., значение


Описание <n> должно принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Локальная переменная с заданным <n> должна содержать величину типа int. Значение локальной переменной, с заданным <n>, записывается в стек операндов.


Примечания Каждая из инструкции iload_<n> выполняет то же, что и iload с явным индексом <n> за исключением того, что операнд <n> задан не явно.





imul imul


Операция Умножает два значения типа int


Формат
imul


Формы imul= 104 (0x68)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу int. Значения считываются с вершины стека операндов. Результат также принадлежит типу int и равен значение1 * значение2. После вычисления результат записывается в стек операндов.

Результат умножения – это младшие 32 бита истинного математического результата, представленного в двоичном дополнительном формате в типе int. Если происходит переполнение, то знак результата может не совпадать со знаком истинного математического результата.

Несмотря на то, что переполнение возможно, исключение инструкцией imul не выбрасывается.





ineg ineg


Операция Инвертирует значение типа int


Формат
ineg


Формы ineg= 116 (0x74)


Стек операндов ..., значение

..., результат


Описание Значение должно принадлежать типу int. Оно считывается со стека операндов. Результат принадлежит типу int и является арифметическим отрицанием значения. Результат записывается в стек операндов.

Для величин, принадлежащих типу int, отрицание – это тоже, что и вычитание из нуля. Поскольку виртуальная машина Java использует для целых чисел представление в двоичном дополнительном коде, а это представление не симметрично, то отрицание максимального по модулю отрицательного числа типа int есть это же число. В этом случае происходит переполнение, однако, несмотря на это исключение не генерируется.

Для всех целых чисел x принадлежащих типу int, -x равно (~x) + 1.





instanceof instanceof


Операция Определяет, принадлежит ли объект заданному типу


Формат
instanceof
байт_индекса1
байт_индекса2


Формы instanceof= 193 (0xc1)


Стек операндов ..., ссылка на объект

..., результат


Описание Ссылка на объект должна принадлежать типу reference. Беззнаковые байт_индекса1 и байт_индекса2 используются для построения индекса массива в константном пуле времени выполнения текущего класса (см. §2.6). Значение индекса определяется как (байт_индекса1 << 8)|(байт_индекса2). Элемент константного пула, на который указывает построенный индекс, должен быть ссылкой на класс, массив или интерфейс.

Если ссылка на объект равна null, то в стек операндов записывается результат 0 с типом int.

В противном случае класс, массив или интерфейс разрешается (см. §5.4.3.1). Если ссылка на объект может быть преобразована к разрешённому ранее классу, массиву или интерфейсу, то в стек операндов записывается результат 1 с типом int. В противном случае инструкция instanceof в стек операндов записывает результат 0 с типом int.


Если ссылка на объект не равна null, то используются следующие правила для разрешения типов: если S - класс, на который ссылается ссылка на объект, а T – разрешаемый класс, массив или интерфейс, то instanceof проверяет следующее:

  • Если S - это класс, тогда:
    • Если T – это класс, то S должно быть такого же класса, как и T либо S должно быть наследником T;
    • Если T – это интерфейс, то S должно реализовывать этот интерфейс;
  • Если S - это интерфейс, тогда:
    • Если T – это класс, тогда T должно быть типа Object.
    • Если T – это интерфейс, то S должно быть тем же интерфейсом или интерфейсом-предком S.
  • Если S – это массив (назовём его SC[], что значит массив с компонентами типа SC), тогда:
    • Если T – это класс, тогда T должен быть Object.
    • Если T – это интерфейс, тогда T должно быть одним из интерфейсов, которые реализует массив (см. JLS §4.10.3).
    • Если T – массив TC[], что значит массив с компонентами типа TC, тогда одно из следующих утверждений должно быть истинным:
      • TC и SC принадлежат одному примитивному типу.
      • TC и SC ссылочные типы и SC можно присвоить TC.


Исключения связывания Во время разрешения символьной ссылки на класс, массив или интерфейс, может быть создано любое исключение, описанное в (§5.4.3.1).


Примечания Инструкция instanceof очень похожа на инструкцию checkcast. Они отличаются друг от друга реакцией на null (checkcast генерирует исключение, instanceof записывает код результата в стек) и влиянием на стек операндов.





invokedynamic invokedynamic


Операция Динамически вызывает метод


Формат
invokedynamic
байт_индекса1
байт_индекса2
0
0


Формы 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;
  • Возвращаемый тип в дескрипторе метода есть java.lang.invoke.CallSite;
  • Типы параметров в дескрипторе метода унаследованы от элементов в стеке операндов следующим образом:
  • Первыми четырьмя типами параметров являются java.lang.invoke.MethodHandle,
java.lang.invoke.MethodHandles.Lookup,
String и
java.lang.invoke.MethodType именно в таком порядке.
  • Если спецификатор узла вызова имеет статические аргументы, тогда для каждого аргумента добавляется в дескриптор метода соответствующий тип. Добавление происходит в том порядке, в котором аргументы были записаны в стек операндов. Типами параметров могут быть Class, java.lang.invoke.MethodHandle, java.lang.invoke.MethodType, String, int, long, float или double.
  • Символьная ссылка на класс, которому принадлежит вызываемый метод, равна java.lang.invoke.MethodHandle.

При этом как будто следующие элементы были бы записаны в стек операндов в указанном порядке:

  • ссылка (тип reference) на объект java.lang.invoke.MethodHandle инициализирующего метода;
  • ссылка (тип reference) на объект java.lang.invoke.MethodHandles.Lookup класса, в котором происходит динамический вызов узла.
  • ссылка (тип reference) на строку (тип String), содержащую имя метода в спецификаторе узла вызова;
  • ссылка (тип reference) на объект java.lang.invoke.MethodType полученный для дескриптора метода в спецификаторе узла вызова;
  • ссылки (тип reference) на классы, типы методов, обработчики методов и строковые литералы, обозначенные как статические аргументы в спецификаторе узла вызова, а также числовые значения (см. §2.3.1, §2.3.2) также обозначенные как статические аргументы в спецификаторе узла вызова в том порядке, в котором они там заданы. Примечание: для примитивных типов автоупаковка и распаковка не происходят.

До тех пор пока инициализирующий метод может быть корректно вызван метода invoke, его дескриптор произволен. Например, первый параметр мог бы быть Object вместо java.lang.invoke.MethodHandles.Lookup, а возвращаемый тип также мог бы быть Object вместо java.lang.invoke.CallSite.

Если инициализирующий метод имеет переменное число параметров, тогда некоторые (или все) аргументы в стеке операндов могут быть собраны в массив параметров соответствующего типа.

Вызов инициализирующего метода происходит в потоке, который выполняет разрешение символьной ссылки спецификаторы узла вызова. Если таких потоков несколько, инициализирующий метод может быть вызван в нескольких потоках одновременно. Поэтому инициализирующие методы, обращающиеся к глобальным данным приложения, должны содержать защиту от такой ошибки многопоточной работы приложения как состояние гонок (конкуренция за ресурсы).

Результат, возвращаемый инициализирующим методом должен быть ссылкой (тип reference) на объект класса java.lang.invoke.CallSite или его наследника. Этот объект называется объектом узла вызова. Эта ссылка считывается из стека операндов также как и при работе инструкции invokevirtual.

Если несколько потоков одновременно исполняют инициализирующий метод для одного и того же динамического узла вызова, то виртуальная машина Java должна определить один объект узла вызова и сделать его видимым всем потокам. Допустимо продолжать выполнение остальных инициализирующих методов, но результаты их выполнения не будут использованы, и выполнение потока динамического узла вызова продолжится с выбранным ранее объектом узла вызова.

Объект узла вызова также является дескриптором (экземпляр java.lang.invoke.MethodType), который должен быть семантически равным дескриптору метода в спецификаторе узла вызова.

Результатом успешного разрешения спецификатора узла вызова является объект узла вызова, связанный перманентно с динамическим узлом вызова.

Затем вызывается обработчик метода, описанного в целевом объекте узла вызова. Вызов происходит эквивалентно вызову инструкции invokevirtual с указанием ей индекса элемента константного пула, являющегося символьной ссылкой на метод, (см. §5.1) со следующими свойствами:

  • Имя метода invokeExact;
  • Дескриптором метода является дескриптор в спецификаторе узла вызова;
  • Символьная ссылка на класс, которому принадлежит вызываемый метод, равна java.lang.invoke.MethodHandle.

Содержимое стека операндов может быть интерпретировано следующим образом: считается, что в стеке есть ссылка (типа 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
байт_индекса1
байт_индекса2
счётчик
0


Формы 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 - это класс, на экземпляр которого ссылается ссылка на объект. Фактический метод для вызова выбирается по следующей процедуре:

  • Если C содержит объявления метода с таким же именем и дескриптором, что и разрешенный ранее интерфейсный метод, то метод для вызова найден и процедура поиска прекращается.
  • Если C имеет предка то, такая же процедура выполняется рекурсивно для всех предков класса до тех пор пока имя метода и дескриптор не совпадут с именем и дескриптором разрешённого ранее интерфейсного метода. Затем процедура поиска прекращается.
  • В противном случае генерируется исключение AbstractMethodError.

Если метод объявлен с модификатором synchronized, то выполняется захват (или повторный захват) монитора связанного со ссылкой объект (как при выполнении инструкции monitorenter для текущего потока).

Если метод объявлен без модификатора native, то аргументы и ссылка на объект считываются из стека операндов. Для метода, который подлежит вызову, создаётся новый фрейм в стеке виртуальной машины Java. Ссылка на объект и значения аргументов записываются в локальные переменные нового фрейма, причём ссылка на объект записывается в локальную переменную 0, первый аргумент - в локальную переменную 1 (если первый аргумент принадлежит типу long или double, то он записывается в локальные переменные 1 и 2) и так далее. Все аргументы, принадлежащие типам данных с плавающей точкой, подвергаются серии преобразований (см. §2.8.3) прежде чем будут сохранены в локальных переменных. Созданный фрейм становится текущим и регистр pc виртуальной машины Java устанавливается так, что бы указывать на индекс первой инструкции вызываемого метода. Выполнение инструкций продолжается с первой инструкции метода.

Если метод объявлен с модификатором native, то и платформенно зависимый код, который реализует метод, ещё не был привязан к виртуальной машине Java (§5.6), то такая привязка происходит. Аргументы и ссылка на объект считываются из стека операндов и передаются как параметры в код, реализующий метод. Все аргументы, принадлежащие типам данных с плавающей точкой, подвергаются серии преобразований (см. §2.8.3) прежде чем будут переданы в качестве параметров. Затем происходит передача параметров и вызов платформенно зависимого кода. Когда платформенно зависимый метод завершает выполнение:

  • Если native метод объявлен synchronized, то монитор, связанный со ссылкой на объект освобождается как при выполнении инструкции monitorexit для текущего потока.
  • Если native метод возвращает значение, то это значение преобразуется из платформенно зависимого формата в тип, с которым объявлен native метод. Затем это значение записывается в стек операндов.


Исключения связывания Может быть выброшено любое исключение, которое может возникнуть при разрешении символьной ссылки на интерфейсный метод (§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
байт_индекса1
байт_индекса2


Формы invokespecial= 183 (0xb7)


Стек операндов ..., ссылка на объект, [арг1, [арг2...]] →

...


Описание Беззнаковые байт_индекса1 и байт_индекса2 используются для построения индекса массива в константном пуле времени выполнения текущего класса (см. §2.6). Значение индекса определяется как (байт_индекса1 << 8)|(байт_индекса2). Элемент константного пула с найденным индексом должен быть символьной ссылкой на метод (см. §5.1). Этот элемент содержит имя и дескриптор метода (см. §4.3.3) а также символьную ссылку на класс, в котором данный метод может быть найден. Указанный метод разрешается (см. §5.4.3.4). Если разрешенный метод объявлен с модификатором protected (см. §4.6) и принадлежит предку текущего класса и при этом в текущем классе он не объявлен, то ссылка на объект должна ссылаться либо на объект текущий класса либо на объект его наследника.

Если все условия, перечисленные ниже, истинные, то управление передаётся разрешённому методу.

  • Для текущего класса установлен флаг ACC_SUPER (см. Таблицу 4.1).
  • Класс разрешённого метода является предком текущего класса.
  • Разрешенный метод не является методом, инициализирующим экземпляр (см. §2.9).

Затем происходит поиск метода, который будет в действительности вызван. Пусть C - это класс-предок, текущего класса. Фактический метод для вызова выбирается по следующей процедуре:

  • Если C содержит объявления метода с таким же именем и дескриптором, что и разрешенный ранее метод, то метод для вызова найден и процедура поиска прекращается.
  • Если C имеет предка то, такая же процедура выполняется рекурсивно для всех предков класса до тех пор пока имя метода и дескриптор не совпадут с именем и дескриптором разрешённого ранее метода. Затем процедура поиска прекращается.
  • В противном случае генерируется исключение AbstractMethodError.

Ссылка на объект должна принадлежать типу reference. За ней в стеке операндов следуют значения аргументов, причём их число, тип и порядок должны соответствовать числу, типу и порядку в дескрипторе выбранного метода.

Если метод объявлен без модификатора native, то аргументы и ссылка на объект считываются из стека операндов. Для метода, который подлежит вызову, создаётся новый фрейм в стеке виртуальной машины Java. Ссылка на объект и значения аргументов записываются в локальные переменные нового фрейма, причём ссылка на объект записывается в локальную переменную 0, первый аргумент - в локальную переменную 1 (если первый аргумент принадлежит типу long или double, то он записывается в локальные переменные 1 и 2) и так далее. Все аргументы, принадлежащие типам данных с плавающей точкой, подвергаются серии преобразований (см. §2.8.3) прежде чем будут сохранены в локальных переменных. Созданный фрейм становится текущим и регистр pc виртуальной машины Java устанавливается так, что бы указывать на индекс первой инструкции вызываемого метода. Выполнение инструкций продолжается с первой инструкции метода.

Если метод объявлен с модификатором native, то и платформенно зависимый код, который реализует метод, ещё не был привязан к виртуальной машине Java (§5.6), то такая привязка происходит. Аргументы и ссылка на объект считываются из стека операндов и передаются как параметры в код, реализующий метод. Все аргументы, принадлежащие типам данных с плавающей точкой, подвергаются серии преобразований (см. §2.8.3) прежде чем будут переданы в качестве параметров. Затем происходит передача параметров и вызов платформенно зависимого кода. Когда платформенно зависимый метод завершает выполнение:

  • Если native метод объявлен synchronized, то монитор, связанный со ссылкой на объект освобождается как при выполнении инструкции monitorexit для текущего потока.
  • Если native метод возвращает значение, то это значение преобразуется из платформенно зависимого формата в тип, с которым объявлен native метод. Затем это значение записывается в стек операндов.


Исключения связывания Может быть выброшено любое исключение, которое может возникнуть при разрешении символьной ссылки на метод (§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 и методов класса предка.


Примечание. В версиях JDK до 1.0.2 инструкция invokespecial называлась invokenonvirtual.


Значения n аргументов и ссылка на объект не взаимно однозначно соответствуют первым n +1 локальным переменным. Аргументы с типами long и double должны быть сохранены в двух локальных переменных с последовательными индексами, поэтому для хранения n аргументов может понадобится более чем n локальных переменных.





invokestatic invokestatic


Операция Вызывает метод класса (static)


Формат
invokestatic
байт_индекса1
байт_индекса2


Формы 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) прежде чем будут переданы в качестве параметров. Затем происходит передача параметров и вызов платформенно зависимого кода. Когда платформенно зависимый метод завершает выполнение:

  • Если native метод объявлен synchronized, то монитор, связанный со ссылкой на объект освобождается как при выполнении инструкции monitorexit для текущего потока.
  • Если native метод возвращает значение, то это значение преобразуется из платформенно зависимого формата в тип, с которым объявлен native метод. Затем это значение записывается в стек операндов.


Исключения связывания Может быть выброшено любое исключение, которое может возникнуть при разрешении символьной ссылки на метод (§5.4.3.3).

Если разрешенный метод принадлежит объекту, то invokestatic генерирует исключение IncompatibleClassChangeError.


Исключения времени выполнения Если выполнение invokestatic приводит к инициализации класса, то может быть выброшена ошибка, более детально описанная в §5.5.

Если выбранный метод объявлен как native и код, который его имплементирует не может быть найден, то invokestatic генерирует UnsatisfiedLinkError.


Примечания Значения n аргументов не взаимно однозначно соответствуют первым n локальным переменным. Аргументы с типами long и double должны быть сохранены в двух локальных переменных с последовательными индексами, поэтому для хранения n аргументов может понадобится более чем n локальных переменных.





invokevirtual invokevirtual


Операция Вызывает метод экземпляра; диспетчеризация основана на классах


Формат
invokevirtual
байт_индекса1
байт_индекса2


Формы 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 - это класс, на экземпляр которого ссылается ссылка на объект. Фактический метод для вызова выбирается по следующей процедуре:

  • Если C содержит объявления метода m, который замещает разрешенный ранее метод (§5.4.5), то метод для вызова найден (это m) и процедура поиска прекращается.
  • Если C имеет предка то, такая же процедура выполняется рекурсивно для всех предков класса до тех пор пока имя метода и дескриптор не совпадут с именем и дескриптором разрешённого ранее метода. Затем процедура поиска прекращается.
  • В противном случае генерируется исключение AbstractMethodError.

Ссылка на объект должна принадлежать типу reference. За ней в стеке операндов следуют значения аргументов, причём их число, тип и порядок должны соответствовать числу, типу и порядку в дескрипторе выбранного метода.

Если метод объявлен без модификатора native, то аргументы и ссылка на объект считываются из стека операндов. Для метода, который подлежит вызову, создаётся новый фрейм в стеке виртуальной машины Java. Ссылка на объект и значения аргументов записываются в локальные переменные нового фрейма, причём ссылка на объект записывается в локальную переменную 0, первый аргумент - в локальную переменную 1 (если первый аргумент принадлежит типу long или double, то он записывается в локальные переменные 1 и 2) и так далее. Все аргументы, принадлежащие типам данных с плавающей точкой, подвергаются серии преобразований (см. §2.8.3) прежде чем будут сохранены в локальных переменных. Созданный фрейм становится текущим и регистр pc виртуальной машины Java устанавливается так, что бы указывать на индекс первой инструкции вызываемого метода. Выполнение инструкций продолжается с первой инструкции метода.

Если метод объявлен с модификатором native, то и платформенно зависимый код, который реализует метод, ещё не был привязан к виртуальной машине Java (§5.6), то такая привязка происходит. Аргументы и ссылка на объект считываются из стека операндов и передаются как параметры в код, реализующий метод. Все аргументы, принадлежащие типам данных с плавающей точкой, подвергаются серии преобразований (см. §2.8.3) прежде чем будут переданы в качестве параметров. Затем происходит передача параметров и вызов платформенно зависимого кода. Когда платформенно зависимый метод завершает выполнение:

  • Если native метод объявлен synchronized, то монитор, связанный со ссылкой на объект освобождается как при выполнении инструкции monitorexit для текущего потока.
  • Если native метод возвращает значение, то это значение преобразуется из платформенно зависимого формата в тип, с которым объявлен native метод. Затем это значение записывается в стек операндов.

Если разрешенный метод является сигнатурно полиморфным (см. §2.9) тогда выполнение инструкции invokevirtual продолжается следующим образом.

Сначала формируется ссылка (тип reference) на экземпляр java.lang.invoke.MethodType как при разрешении символьной ссылки на тип метода (см. §5.4.3.5) с такими же параметрами и возвращаемым типом как и в дескрипторе метода, полученного по ссылке инструкции invokevirtual.

  • Если названный выше метод это invokeExact, то экземпляр java.lang.invoke.MethodType должен быть семантически равным дескриптору обработчика метода объекта, на который ссылается ссылка на объект. Будет вызван обработчик метода по ссылке на объект.
  • Если названный выше метод это invoke и экземпляр java.lang.invoke.MethodType семантически равен дескриптору обработчика метода объекта, на который ссылается ссылка на объект, тогда будет вызван обработчик метода по ссылке на объект.
  • Если названный выше метод это invoke и экземпляр java.lang.invoke.MethodType семантически не равен дескриптору обработчика метода объекта, на который ссылается ссылка на объект, тогда виртуальная машина Java пытается преобразовать дескриптор типов полученного обработчика метода, как при вызове java.lang.invoke.MethodHandle.asType, чтобы получить точный обработчик метода m. Будет вызван обработчик метода m.

В стеке операндов за ссылкой на объект должны следовать значения аргументов прим их число, тип и порядок следования должны соответствовать числу, типу и порядку следования описанному в дескрипторе типа вызываемого метода. (Дескриптор типа должен соответствовать дескриптору метода (с учётом типа обработчика метода), как указано в §5.4.3.5.)

Далее, если обработчик метода, который необходимо вызвать, реализован в виде байт-кода, виртуальная машина Java выполняет обработчик метода с учётом типа обработчика метода. Если тип обработчика метода есть 5 (REF_invokeVirtual), 6 (REF_invokeStatic), 7 (REF_invokeSpecial), 8 (REF_newInvokeSpecial) или 9 (REF_invokeInterface), то создаётся фрейм и назначается текущим для выполнения соответствующего байт кода. Когда метод, выполняющий байт код завершается (нормально или аварийно), то фрейм вызвавшего его метода считается фреймом, содержащим инструкцию invokevirtual.


Примечание. Фрейм, в котором выполняется непосредственно байт код, считается невидимым.


Если обработчик метода, который необходимо вызвать, не реализован в виде байт-кода, виртуальная машина Java выполняет действия по запуску платформенно зависимых методов.


Исключения связывания Может быть выброшено любое исключение, которое может возникнуть при разрешении символьной ссылки на метод (§5.4.3.3).

Если разрешенный метод является статическим, то invokevirtual генерирует исключение IncompatibleClassChangeError.

Если разрешенный метод является сигнатурно полиморфным, то во время разрешения типа метода, полученного из дескриптора по символьной ссылке на метод, могут быть сгенерированы любые исключения, связанные с разрешением типов (см. §5.4.3.5)


Исключения времени выполнения Если ссылка на объект есть null, то инструкция invokevirtual генерирует NullPointerException.

Если разрешенный метод не является сигнатурно полиморфным:

  • Если не был найден метод, соответствующий выбранному имени и дескриптору, то invokevirtual генерирует AbstractMethodError.
  • Если выбранный метод - абстрактный, то invokevirtual генерирует AbstractMethodError.
  • Если выбранный метод объявлен как native и код, который его имплементирует не может быть найден, то invokevirtual генерирует UnsatisfiedLinkError.

Если разрешенный метод является сигнатурно полиморфным:

  • Если имя метода есть invokeExact и полученный экземпляр java.lang.invoke.MethodType не является семантически равным дескриптору типа метода обработчика, то invokevirtual генерирует java.lang.invoke.WrongMethodTypeException.
  • Если имя метода есть invoke и полученный экземпляр java.lang.invoke.MethodType не является допустимым аргументом для java.lang.invoke.MethodHandle.asType то invokevirtual генерирует java.lang.invoke.WrongMethodTypeException.


Примечания Значения n аргументов и ссылка на объект не взаимно однозначно соответствуют первым n +1 локальным переменным. Аргументы с типами long и double должны быть сохранены в двух локальных переменных с последовательными индексами, поэтому для хранения n аргументов может понадобится более чем n локальных переменных.





ior ior


Операция Логическое «или» над значениями типа int


Формат
ior


Формы ior= 128 (0x80)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу int. Они считываются из стека операндов. Результат также принадлежит типу int и представляет собой побитовое "ИЛИ" над значением1 и значением2. Затем результат записывается в стек операндов.





irem irem


Операция Остаток от деления значений типа int


Формат
irem


Формы 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


Формы 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


Формы ishl= 120 (0x78)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу int. Они считываются из стека операндов. Результат также принадлежит типу int и представляет собой значение1 сдвинутое влево на s позиций, где s – это младшие 5 битов значения2. Затем результат записывается в стек операндов.


Примечания Операция сдвига влево эквивалентна (даже в случае переполнения) умножению исходного значения на 2 в степени s. Количество бит, на которое нужно сдвинуть значение, всегда находится в пределах от 0 до 31 включительно, как если бы до сдвига над значением2 было выполнено логическое «И» с маской 0x1f.





ishr ishr


Операция Арифметический сдвиг вправо значения типа int


Формат
ishr


Формы 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
индекс


Формы istore= 54 (0x36)


Стек операндов ..., значение

...


Описание Индекс является беззнаковым байтом. Индекс должен принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Значение на вершине стека операндов должно принадлежать типу int. Оно считывается из стека операндов, затем в локальную переменную с индексом индекс записывается значение.


Примечания Инструкция istore может быть использована совместно с инструкцией wide, когда необходимо задать двухбайтовый беззнаковый индекс локальной переменной.





istore_<n> istore_<n>


Операция Считывает из стека значение типа int и записывает в локальную переменную


Формат
istore_<n>


Формы istore_0= 59 (0x3b)

istore_1= 60 (0x3c)

istore_2= 61 (0x3d)

istore_3= 62 (0x3e)


Стек операндов ..., значение

...


Описание <n>должно принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Значение на вершине стека операндов должно принадлежать типу int. Оно считывается из стека операндов, затем в локальную переменную с индексом <n>записывается значение.


Примечания Каждая из инструкции istore_<n> выполняет то же, что и istore с явным индексом <n> за исключением того, что операнд <n> задан не явно.





isub isub


Операция Вычитает значения типа int


Формат
isub


Формы isub= 100 (0x64)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу int. Они считываются с вершины стек операндов. Результат типа int есть значение1 - значение2. Результат записывается в стек операндов.

Для целочисленного вычитания выражение a-b дает такой же результат, что и a+(-b). Для значений типа int вычитание из нуля есть то же самое, что и отрицание числа.

Результат вычитания - это младшие 32 бита результата точного вычитания, представленные в двоичном дополнительном коде. Если происходит переполнение, то знак результата может отличаться от знака математической разности двух значений.

Не смотря на то, что при выполнении инструкции isub может произойти переполнение, инструкция isub никогда не приводит к исключению времени выполнения.





iushr iushr


Операция Логический сдвиг вправо значения типа int


Формат
iushr


Формы iushr= 124 (0x7c)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу int. Они считываются из стека операндов. Результат также принадлежит типу int и представляет собой значение1 сдвинутое вправо на s позиций с заполнением нулями освободившихся позиций, где s – это младшие 5 битов значения2. Затем результат записывается в стек операндов.


Примечания Если значение1 положительно и s равно значение2 & 0x1f, то результат сдвига равен значение1 >> s; если значение1 отрицательно, то результат равен выражению (значение1 >> s) + (2 <<~s). Добавление слагаемого (2 <<~s) эквивалентно тому, что знаковый бит при сдвиге будет заменён нулём. Количество бит, на которое нужно сдвинуть значение, всегда находится в пределах от 0 до 31 включительно.





ixor ixor


Операция Исключающее «или» над значениями типа int


Формат
ixor


Формы ixor= 130 (0x82)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу int. Они считываются из стека операндов. Результат также принадлежит типу int и представляет собой результат операции «исключающее ИЛИ» над значением1 и значением2. Затем результат записывается в стек операндов.





jsr jsr


Операция Вызов подпрограммы


Формат
jsr
байт_адреса1
байт_адреса2


Формы 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
байт_адреса1
байт_адреса2
байт_адреса3
байт_адреса4


Формы 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


Формы l2d= 138 (0x8a)


Стек операндов ..., значение

..., результат


Описание Значение на вершине стека операндов должно принадлежать типу long. Оно считывается с вершины стека операндов и преобразуется к результату типа double, согласно правилам округления к ближайшему стандарта IEEE 754. Результат записывается в стек операндов.


Примечания Инструкция l2d выполняет расширяющее преобразование примитивных типов (см. JLS §5.1.2), что может привести к потере точности, поскольку мантисса числа типа double имеет только 53 значащих бита.





l2f l2f


Операция Преобразует значение типа long к типу float


Формат
l2f


Формы l2f= 137 (0x89)


Стек операндов ..., значение

..., результат


Описание Значение на вершине стека операндов должно принадлежать типу long. Оно считывается с вершины стека операндов и преобразуется к результату типа float, согласно правилам округления к ближайшему стандарта IEEE 754. Результат записывается в стек операндов.


Примечания Инструкция l2f выполняет расширяющее преобразование примитивных типов (см. JLS §5.1.2), что может привести к потере точности, поскольку мантисса числа типа float имеет только 24 значащих бита.





l2i l2i


Операция Преобразует значение типа long к типу int


Формат
l2i


Формы l2i= 136 (0x88)


Стек операндов ..., значение

..., результат


Описание Значение на вершине стека операндов должно принадлежать типу long. Оно считывается с вершины стека операндов и преобразуется к результату типа int, следующим образом: в качестве результата берутся младшие 32 бита значения long, старшие 32 бита игнорируются. Результат записывается в стек операндов.


Примечания Инструкция l2i выполняет сужающее преобразование примитивных типов (см. JLS §5.1.2), что может привести к полной потере исходного значения. Знак результата также может отличаться от знака исходного значения.





ladd ladd


Операция Складывает два значения типа long


Формат
ladd


Формы ladd= 97 (0x61)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу long. Они считываются с вершины стек операндов. Результат типа long есть значение1 + значение2. Результат записывается в стек операндов.

Результат сложения - это младшие 64 бита результата точного сложения, представленные в двоичном дополнительном коде. Если происходит переполнение, то знак результата может отличаться от знака математической суммы двух значений.

Не смотря на то, что при выполнении инструкции ladd может произойти переполнение, инструкция ladd никогда не приводит к исключению времени выполнения.





laload laload


Операция Записывает в стек значение long из массива


Формат
laload


Формы laload= 47 (0x2f)


Стек операндов ..., ссылка на массив, индекс

..., значение


Описание Ссылка на массив должна быть типа reference и ссылаться на массив, чьи компоненты значения типа long. Индекс должен принадлежать типу int. Как ссылка на массив, так и индекс считываются из стека операндов. Значение типа long считывается из элемента массива с соответствующим индексом и записывается в стек операндов.


Исключения времени выполнения Если ссылка на массив равна null, то laload генерирует NullPointerException. В противном случае, если индекс вне границ массива, генерируется исключение ArrayIndexOutOfBoundsException.





land land


Операция Булево «И» над значениями типа long


Формат
land


Формы land= 127 (0x7f)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу long. Они считываются с вершины стека операндов. Результат типа long есть логическое "И" над значением1 и значеним2. Результат записывается в стек операндов.





lastore lastore


Операция Загружает значение типа long из стека в массив


Формат
lastore


Формы lastore= 80 (0x50)


Стек операндов ..., ссылка на массив, индекс, значение

...


Описание Ссылка на массив должна быть типа reference и ссылаться на массив, чьи компоненты значения типа long. Индекс должен принадлежать типу int, значение должно принадлежать типу long. Ссылка на массив, индекс и значение считываются из стека операндов. Затем значение сохраняется в массиве с заданным индексом.


Исключения времени выполнения Если ссылка на массив равна null, то lastore генерирует NullPointerException. В противном случае, если индекс вне границ массива, генерируется исключение ArrayIndexOutOfBoundsException.





lcmp lcmp


Операция Сравнивает два значения типа long


Формат
lcmp


Формы 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_<l>


Формы lconst_0= 9 (0x9)

lconst_1= 10 (0xa)


Стек операндов ...→

..., <l>


Описание Записывает константу <l> (0 или 1) типа long в стек операндов.





ldc 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
байт_индекса1
байт_индекса2


Формы 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
байт_индекса1
байт_индекса2


Формы 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


Формы 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
индекс


Формы lload= 22 (0x16)


Стек операндов ...→

..., значение


Описание Индекс является беззнаковым байтом. Индекс и величина индекс+1 должны принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Локальная переменная с заданным индексом должна содержать величину типа long. Значение локальной переменной, с заданным индексом, записывается в стек операндов.


Примечания Инструкция lload может быть использована совместно с инструкцией wide, когда необходимо задать двухбайтовый беззнаковый индекс локальной переменной.





lload_<n> lload_<n>


Операция Загружает значение типа long из локальной переменной в стек


Формат
lload_<n>


Формы lload_0= 30 (0x1e)

lload_1= 31 (0x1f)

lload_2= 32 (0x20)

lload_3= 33 (0x21)


Стек операндов ...→

..., значение


Описание И <n> и величина <n>+1 должны принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Локальная переменная с индексом <n> должна содержать величину типа long. Значение локальной переменной с индексом <n>, записывается в стек операндов.


Примечания Каждая из инструкции lload_<n> выполняет то же, что и lload с явным индексом <n> за исключением того, что операнд <n> задан не явно.





lmul lmul


Операция Умножает два значения типа long


Формат
lmul


Формы lmul= 105 (0x69)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу long. Значения считываются с вершины стека операндов. Результат также принадлежит типу long и равен значение1 * значение2. После вычисления результат записывается в стек операндов.

Результат умножения – это младшие 64 бита истинного математического результата, представленного в двоичном дополнительном формате в типе long. Если происходит переполнение, то знак результата может не совпадать со знаком истинного математического результата.

Несмотря на то, что переполнение возможно, исключение инструкцией lmul не выбрасывается.





lneg lneg


Операция Инвертирует значение типа long


Формат
lneg


Формы lneg= 117 (0x75)


Стек операндов ..., значение

..., результат


Описание Значение должно принадлежать типу long. Оно считывается со стека операндов. Результат принадлежит типу long и является арифметическим отрицанием значения. Результат записывается в стек операндов.

Для величин, принадлежащих типу long, отрицание – это тоже, что и вычитание из нуля. Поскольку виртуальная машина Java использует для целых чисел представление в двоичном дополнительном коде, а это представление не симметрично, то отрицание максимального по модулю отрицательного числа типа long есть это же число. В этом случае происходит переполнение, однако, несмотря на это исключение не генерируется.

Для всех целых чисел x принадлежащих типу long, -x равно (~x) + 1.





lookupswitch lookupswitch


Операция Выполняет переход, если ключ в стеке совпадает с ключом в таблице переходов


Формат
lookupswitch
<байты 0-3 выравнивающего смещения>
байт_смещения_по_умолчанию1
байт_смещения_по_умолчанию2
байт_смещения_по_умолчанию3
байт_смещения_по_умолчанию4
пара_значение1-смещение1
пара_значение2-смещение2
пара_значение3-смещение3
пара_значение4-смещение4
другие пары_значение-смещение'


Формы 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


Формы lor= 129 (0x81)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу long. Они считываются из стека операндов. Результат также принадлежит типу long и представляет собой побитовое "или" над значением1 и значением2. Затем результат записывается в стек операндов.





lrem lrem


Операция Остаток от деления значений типа long


Формат
lrem


Формы 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


Формы 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


Формы lshl= 121 (0x79)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу long. Они считываются из стека операндов. Результат также принадлежит типу long и представляет собой значение1 сдвинутое влево на s позиций, где s – это младшие 6 битов значения2. Затем результат записывается в стек операндов.


Примечания Операция сдвига влево эквивалентна (даже в случае переполнения) умножению исходного значения на 2 в степени s. Количество бит, на которое нужно сдвинуть значение, всегда находится в пределах от 0 до 63 включительно, как если бы до сдвига над значением2 было выполнено логическое «И» с маской 0x3f.





lshr lshr


Операция Арифметический сдвиг вправо значения типа long


Формат
lshr


Формы 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
индекс


Формы lstore= 55 (0x37)


Стек операндов ..., значение

...


Описание Индекс является беззнаковым байтом. Индекс и величина индекс+1 должны принадлежать массиву локальных переменных текущего фрейма (см. §2.6). Значение на вершине стека операндов должно принадлежать типу long. Оно считывается из стека операндов. В локальные переменные с индексами индекс и индекс+1 записывается значение.


Примечания Инструкция lstore может быть использована совместно с инструкцией wide, когда необходимо задать двухбайтовый беззнаковый индекс локальной переменной.





lstore_<n> lstore_<n>


Операция Считывает из стека значение типа long и записывает в локальную переменную


Формат
lstore_<n>


Формы 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


Формы lsub= 101 (0x65)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу long. Они считываются с вершины стек операндов. Результат типа long есть значение1 - значение2. Результат записывается в стек операндов.

Для целочисленного вычитания выражение a-b дает такой же результат, что и a+(-b). Для значений типа long вычитание из нуля есть то же самое, что и отрицание числа.

Результат вычитания - это младшие 64 бита результата точного вычитания, представленные в двоичном дополнительном коде. Если происходит переполнение, то знак результата может отличаться от знака математической разности двух значений.

Не смотря на то, что при выполнении инструкции lsub может произойти переполнение, инструкция lsub никогда не приводит к исключению времени выполнения.





lushr lushr


Операция Логический (беззнаковый) сдвиг вправо значения типа long


Формат
lushr


Формы 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


Формы lxor= 131 (0x83)


Стек операндов ..., значение1, значение2

..., результат


Описание И значение1 и значение2 должны принадлежать типу long. Они считываются из стека операндов. Результат также принадлежит типу long и представляет собой результат операции «исключающее ИЛИ» над значением1 и значением2. Затем результат записывается в стек операндов.





monitorenter 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


Формы 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 -методах:

  • Освобождение монитора при нормальном завершении synchronized-метода выполняет виртуальная машина Java с помощью инструкции возврата из метода. Освобождение монитора при аварийном завершении synchronized-метода также выполняет виртуальная машина Java с помощью инструкции athrow.
  • Если исключение генерируется в synchronized-блоке, освобождение монитора, захваченного при входе в synchronized-блок выполняется за счет механизма поддержки исключений виртуальной машины Java (§3.14).





multianewarray multianewarray


Операция Создаёт новый многомерный массив


Формат
multianewarray
байт_индекса1
байт_индекса2
число_измерений


Формы 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
байт_индекса1
байт_индекса2


Формы 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
код_типа_компонентов_массива


Формы newarray= 188 (0xbc)


Стек операндов ..., количество элементов

..., ссылка на массив


Описание Количество элементов должно принадлежать типу int. Оно считывается из стека операндов.

Код_типа_компонентов_массива может принимать одно из следующих значений:

Таблица. Коды типов массива

Тип массива Код_типа_компонентов_массива
T_BOOLEAN 4
T_CHAR 5
T_FLOAT 6
T_DOUBLE 7
T_BYTE 8
T_SHORT 9
T_INT 10
T_LONG 11


В куче создаётся новый новый массив, чьи компоненты имеют тип, соответствующий указанному коду. Ссылка на массив типа reference записывается в стек операндов. Каждый элемент массива инициализируется значением по умолчанию (см. §2.3, §2.4) для своего собственного типа.


Исключения времени выполнения Если количество элементов меньше нуля, то инструкция newarray генерирует исключение NegativeArraySizeException.


Примечания В реализации виртуальной машины Java компании Oracle, массивы с типом boolean (код_типа_элементов_массива есть T_BOOLEAN) хранятся в виде последовательности байт (один байт хранит одно значение типа boolean). Доступ к таким массивам осуществляется посредством инструкций baload и bastore, которые также используются для работы массивами типа byte. Другие реализации виртуальной машины могут использовать упакованные массивы типа boolean, однако доступ к элементам таких массивов также должен выполняться с помощью инструкций baload и bastore.





nop nop


Операция Не делает ничего


Формат
nop


Формы nop= 0 (0x0)


Стек операндов Нет

Без изменений


Описание Не делает ничего





pop pop


Операция Считывает операнд с вершины стека


Формат
pop


Формы pop= 87 (0x57)


Стек операндов ..., значение

...


Описание Считывает значения из стека операндов.

Инструкция pop только если тип значения принадлежит категории 1 (см. §2.11.1)





pop2 pop2


Операция Считывает один или два операнда с вершины стека


Формат
pop2


Формы pop2= 88 (0x58)


Стек операндов Форма 1:


..., значение1, значение2

...

где значение1, значение2 – это значения из категории 1 вычислимых типов (см. §2.11.1)


Форма 2:


..., значение

...

где значение – это значение из категории 1 вычислимых типов (см. §2.11.1)


Описание Считывает одно или два значения из стека операндов.





putfield putfield


Операция Записывает значение в поле объекта


Формат
putfield
байт_индекса1
байт_индекса2


Формы 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
байт_индекса1
байт_индекса2


Формы 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
индекс


Формы 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


Формы 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


Формы saload= 53 (0x35)


Стек операндов ..., ссылка на массив, индекс

..., значение


Описание Ссылка на массив должна быть типа reference и ссылаться на массив, чьи компоненты значения типа short. Индекс должен принадлежать типу int. Как ссылка на массив, так и индекс считываются из стека операндов. Значение типа short считывается из элемента массива с соответствующим индексом и записывается в стек операндов.


Исключения времени выполнения Если ссылка на массив равна null, то saload генерирует NullPointerException. В противном случае, если индекс вне границ массива, генерируется исключение ArrayIndexOutOfBoundsException.





sastore sastore


Операция Записывает значение типа short из стека в массив


Формат
sastore


Формы sastore= 86 (0x56)


Стек операндов ..., ссылка на массив, индекс, значение

...


Описание Ссылка на массив должна быть типа reference и ссылаться на массив, чьи компоненты значения типа short. Индекс должен принадлежать типу int, значение должно принадлежать типу short. Ссылка на массив, индекс и значение считываются из стека операндов. Затем значение сохраняется в массиве с заданным индексом.


Исключения времени выполнения Если ссылка на массив равна null, то sastore генерирует NullPointerException. В противном случае, если индекс вне границ массива, генерируется исключение ArrayIndexOutOfBoundsException.





sipush sipush


Операция Записывает в стек значение типа short


Формат
sipush
байт1
байт2


Формы sipush= 17 (0x11)


Стек операндов ...→

..., значение


Описание Промежуточные байт1 и байт2 преобразуются в значение типа short: (байт1 << 8) | байт2. Затем полученное значение расширяется с учётом знака до int, которое и записывается в стек операндов.





swap swap


Операция Меняет местами два операнда на вершине стека


Формат
swap


Формы swap= 95 (0x5f)


Стек операндов ..., значение2, значение1

..., значение1, значение2


Описание Меняет местами два значение на вершине стека операндов.

Инструкция swap должна использоваться только, если тип значения1 и значения2 принадлежит первой категории вычислимых типов (см. §2.11.1)


Примечания Виртуальная машина Java не имеет инструкции для перемены местами значений, чей тип принадлежит категории 2 вычислимых типов.





tableswitch tableswitch


Операция Выполняет переход в зависимости от индекса смещения в стеке


Формат
tableswitch
<байты 0-3 выравнивающего смещения>
байт_смещения_по_умолчанию1
байт_смещения_по_умолчанию2
байт_смещения_по_умолчанию3
байт_смещения_по_умолчанию4
байт_нижней_границы1
байт_нижней_границы2
байт_нижней_границы3
байт_нижней_границы4
байт_верхней_границы1
байт_верхней_границы2
байт_верхней_границы3
байт_верхней_границы4
смещения переходов


Формы 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
wide
<код операции>
байт_индекса1
байт_индекса2


где <код операции> принимает значение iload, fload, aload, lload, dload, istore, fstore, astore, lstore, dstore, или ret


Формат 2
wide
iinc
байт_индекса1
байт_индекса2
байт_константы1
байт_константы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: её адрес не может быть целевым адресом переход при передаче управления.