Инструкция виртуальной машины Java состоит из кода операции длиной в байт (Opcode), который представляет определенное значение, за которым следуют ноль или более операндов, представляющих параметры операции. Многие инструкции виртуальной машины не содержат операндов, а содержат только код операции. Если исключение игнорируется, интерпретатор JVM может эффективно работать всего с одним кодом.
Скопируйте код кода следующим образом:
делать{
Автоматически вычислять регистр ПК и получать код операции из местоположения регистра ПК.
if(операнд существует) удалить операнд;
Выполните операцию, определенную опкодом;
} while (обработка следующего цикла)
Количество и длина операндов зависят от кода операции. Если длина операнда превышает один байт, он будет сохранен в порядке Big-Endian (первый байт-код высокого класса), а его значение должно быть (байт1<<8) | байт2.
Поток инструкций байт-кода выровнен по одному байту, за исключением инструкций «tableswitch» и «lookupswitch». Их операнды являются специальными и разделены на 4 байта. Для достижения выравнивания необходимо зарезервировать соответствующие пробелы.
Ограничение длины кода операции виртуальной машины Java одним байтом и отказ от выравнивания длины параметров скомпилированного кода означает получение короткого и компактного скомпилированного кода, даже если это может стоить реализации JVM определенных затрат производительности. Поскольку код операции может иметь длину только один байт, он ограничивает количество наборов инструкций и не предполагает, что данные хорошо выровнены, а это означает, что, когда данные превышают один байт, конкретная структура данных должна быть восстановлена из байты. Некоторая производительность будет потеряна.
Типы данных и виртуальная машина Java
В наборе команд JVM большинство инструкций содержат информацию о типах данных, соответствующую их операциям. Например, инструкция iload загружает данные типа int из таблицы локальных переменных в стек операндов, а команда fload загружает данные типа float.
Для большинства инструкций байт-кода, связанных с типами данных, их мнемоника кода операции имеет специальные символы, обозначающие: i представляет тип int, l представляет собой long, s представляет собой short, b представляет собой байт, c представляет собой char, f обозначает тип float, d обозначает double и означает ссылку. Существуют отдельные директивы, которые при необходимости можно использовать для преобразования неподдерживаемых типов в поддерживаемые.
инструкции по загрузке и сохранению
Инструкции загрузки и сохранения используются для передачи данных в и из таблицы локальных переменных стекового фрейма и стека операндов.
1) Инструкции по загрузке локальной переменной в стек операндов включают: iload, iload_<n>, lload, lload_<n>, float, fload_<n>, dload, dload_<n>, aload, aload_<n>.
2) Инструкции по сохранению значения из стека операндов в локальной переменной: istore,istore_<n>,lstore,lstore_<n>,fstore,fstore_<n>,dstore,dstore_<n>,astore,astore_<n>
3) Инструкции по загрузке констант в стек операндов: bipush, sipush, ldc, ldc_w, ldc2_w, aconst_null, iconst_ml, iconst_<i>, lconst_<l>, fconst_<f>, dconst_<d>
4) Инструкция индекса доступа к таблице локальных переменных: широкая
Некоторые инструкции, заканчивающиеся угловыми скобками, представляют собой группу инструкций, например iload_<i>, которая представляет iload_0, iload_1 и т. д. Эти группы инструкций представляют собой общие инструкции с одним операндом.
Инструкции по эксплуатации
Арифметические инструкции используются для выполнения определенной операции над значениями в двух стеках операндов и сохранения результата обратно в вершину стека операций.
1) Инструкции по сложению: iadd,ladd,fadd,dadd
2) Инструкции вычитания: isub, lsub, fsub, dsub.
3) Инструкции умножения: imul, lmul, fmul, dmul
4) Инструкции деления: idiv, ldiv, fdiv, ddiv
5) Остальные инструкции: ирем, лрем, фрем, дрем.
6) Отрицательные инструкции: ineg, length, fneg, dneg.
7) Инструкции по перемещению: ishl,ishr,iushr,lshl,lshr,lusr
8) Побитовые инструкции ИЛИ: ior, lor
9) Побитовые инструкции И: iand, земля
10) Побитовые инструкции XOR: ixor, lxor
11) Инструкция увеличения локальной переменной: iinc
12) Инструкции по сравнению: dcmpg, dcmpl, fcmpg, fcmpl, lcmp
Виртуальная машина Java явно не предусматривает переполнение целочисленных данных, но предусматривает, что при обработке целочисленных данных только инструкции деления и остатка заставят виртуальную машину выдать исключение, когда делитель равен 0.
инструкции по загрузке и сохранению
Инструкции загрузки и сохранения используются для передачи данных в и из таблицы локальных переменных кадра стека и стека операндов.
1) Инструкции по загрузке локальной переменной в стек операндов включают: iload, iload_<n>, lload, lload_<n>, float, fload_<n>, dload, dload_<n>, aload, aload_<n>.
2) Инструкции по сохранению значения из стека операндов в локальной переменной: istore,istore_<n>,lstore,lstore_<n>,fstore,fstore_<n>,dstore,dstore_<n>,astore,astore_<n>
3) Инструкции по загрузке констант в стек операндов: bipush, sipush, ldc, ldc_w, ldc2_w, aconst_null, iconst_ml, iconst_<i>, lconst_<l>, fconst_<f>, dconst_<d>
4) Инструкция индекса доступа к таблице локальных переменных: широкая
Некоторые инструкции, заканчивающиеся угловыми скобками, представляют собой группу инструкций, например iload_<i>, которая представляет iload_0, iload_1 и т. д. Эти группы инструкций представляют собой общие инструкции с одним операндом.
Инструкции по эксплуатации
Арифметические инструкции используются для выполнения определенной операции над значениями в двух стеках операндов и сохранения результата обратно в вершину стека операций.
1) Инструкции по сложению: iadd,ladd,fadd,dadd
2) Инструкции вычитания: isub, lsub, fsub, dsub.
3) Инструкции умножения: imul, lmul, fmul, dmul
4) Инструкции деления: idiv, ldiv, fdiv, ddiv
5) Остальные инструкции: ирем, лрем, фрем, дрем.
6) Отрицательные инструкции: ineg, length, fneg, dneg.
7) Инструкции по перемещению: ishl,ishr,iushr,lshl,lshr,lusr
8) Побитовые инструкции ИЛИ: ior, lor
9) Побитовые инструкции И: iand, земля
10) Побитовые инструкции XOR: ixor, lxor
11) Инструкция увеличения локальной переменной: iinc
12) Инструкции по сравнению: dcmpg, dcmpl, fcmpg, fcmpl, lcmp
Виртуальная машина Java явно не предусматривает переполнение целочисленных данных, но предусматривает, что при обработке целочисленных данных только инструкции деления и остатка заставят виртуальную машину выдать исключение, когда делитель равен 0.
инструкции по преобразованию типов
Инструкции преобразования типов преобразуют два числовых типа виртуальной машины Java друг в друга. Эти операции обычно используются для реализации явных операций преобразования типов в пользовательском коде.
JVM поддерживает преобразование расширенного типа (преобразование типа малого диапазона в преобразование типа большого диапазона):
1) От типа Int до long, float, double.
2) длинный тип для плавающего типа, двойной тип
3) плавать до двойного типа
Инструкции преобразования узкого типа: i2b, i2c, i2s, l2i, f2i, f2l, d2l и d2f. Преобразование узкого типа может привести к тому, что результаты преобразования будут иметь разные знаки и порядки. Процесс преобразования может привести к потере точности числового значения. Например, когда тип int или long преобразуется в целочисленный тип T, процесс преобразования отбрасывает только неожиданное содержимое младших N байтов (N — длина типа данных типа T).
Создание и манипулирование объектами
Хотя экземпляры классов и массивы являются объектами, виртуальная машина Java использует разные инструкции байт-кода для создания и работы экземпляров классов и массивов.
1) Инструкция по созданию экземпляра: новый
2) Инструкция по созданию массивов: newarray, anewarray, multianewarray
3) Инструкции доступа к полям: getfield, putfield, getstatic, putstatic.
4) Загрузка элементов массива в инструкции стека операндов: baload, caload, saload, iaload, laload, faload, daload, aaload
5) Сохраните значение стека операндов в элементе массива и выполните: bastore,castore,castore,sastore,iastore,fastore,dastore,aastore
6) Получите инструкцию длины массива: arraylength
7) Проверьте инструкции типа экземпляра: instanceof, checkcast
Инструкции по управлению стеком операндов
Инструкции, которые напрямую управляют стеком операндов: pop, pop2, dup, dup2, dup_x1, dup2_x1, dup_x2, dup2_x2 и swap.
команда передачи управления
Позволяет JVM условно или безоговорочно продолжить выполнение программы с инструкции, следующей за указанной инструкцией, а не с инструкции передачи управления. Инструкции по передаче управления включают в себя:
1) Условный переход: ifeq, iflt, ifle, ifne, ifgt, ifge, ifnull, ifnotnull, if_cmpeq, if_icmpne, if_icmlt, if_icmpgt и т.д.
2) Составное условное ветвление: tableswitch, Lookupswitch.
3) Безусловная ветвь: goto,goto_w,jsr,jsr_w,ret
В JVM имеется специальный набор инструкций для обработки операций сравнения условных переходов типов int и ссылочных. Чтобы четко указать, является ли значение объекта нулевым, существуют специальные инструкции для обнаружения нулевых значений. Операции сравнения условного перехода логического и байтового типа, типа char и короткого типа выполняются с использованием инструкций сравнения типа int, тогда как операции сравнения длинных, плавающих и двойных условных ветвей выполняются инструкциями операции сравнения соответствующего типа, а операция инструкции вернут Целочисленное значение добавляется в стек операндов, а затем выполняется операция условного сравнения типа int для завершения перехода всей ветки. Все типы сравнений в конечном итоге будут преобразованы в операции сравнения типов int.
Инструкции по вызову и возврату метода
Инструкция вызова виртуальной машины: вызов метода экземпляра объекта и его отправка в соответствии с фактическим типом объекта (отправка виртуальной машины).
Инструкция вызова интерфейса: вызовите метод интерфейса, найдите объект, реализующий этот метод интерфейса во время выполнения, и найдите соответствующий метод для вызова.
ignorespecial: вызов методов экземпляра, требующих специальной обработки, включая методы инициализации экземпляра, частные методы и методы родительского класса.
ignorestatic: вызов метода класса (статический)
Инструкции возврата метода различаются по типу возвращаемого значения, включая ireturn (возвращаемое значение — логическое, байтовое, символьное, короткое и целое), lreturn, freturn, drturn и areturn. Другой возврат предназначен для метода void, метода инициализации экземпляра. , class и используется метод инициализации класса i интерфейса.
синхронный
JVM поддерживает синхронизацию на уровне метода и синхронизацию последовательности инструкций внутри метода, оба из которых реализуются через мониторы.
Синхронизация на уровне метода является неявной и не требует управления с помощью инструкций байт-кода. Она реализуется в вызовах методов и операциях возврата. Виртуальная машина определяет, является ли это синхронным методом, по флагу ACC_SYNCHRONIZED в стандартной структуре метода в пуле констант метода. При вызове метода вызывающая инструкция проверяет, установлен ли флаг. Если он установлен, поток выполнения удерживает монитор, затем выполняет метод и, наконец, освобождает монитор после завершения метода.
Синхронизируйте последовательность наборов инструкций, обычно отмеченную синхронизированным блоком. Набор инструкций JVM имеет MonitorEnter и Monitorexit для поддержки синхронизированной семантики.
Структурированная блокировка — это когда каждый выход монитора во время вызова метода соответствует предыдущей записи монитора. JVM гарантирует, что структурированные блокировки устанавливаются с помощью следующих двух правил (T представляет поток, M представляет монитор):
1) Количество раз, когда T удерживает M во время выполнения метода, должно быть равно количеству раз, когда T освобождает M после завершения метода.
2) Никогда и никогда не возникнет ситуация, когда T отпускает M больше раз, чем T удерживает M.