Байт код что это
Перейти к содержимому

Байт код что это

  • автор:

Байт-код

Байт-код или байтко́д (англ.  byte-code ), иногда также используется термин псевдоко́д — машинно-независимый код низкого уровня, генерируемый транслятором и исполняемый интерпретатором. Большинство инструкций байт-кода эквивалентны одной или нескольким командам ассемблера. Трансляция в байт-код занимает промежуточное положение между компиляцией в машинный код и интерпретацией.

Байт-код называется так, потому что длина каждого кода операции — один байт, но длина кода команды различна. Каждая инструкция представляет собой однобайтовый код операции от 0 до 255, за которым следуют такие параметры, как регистры или адреса памяти. Это в типичном случае, но спецификация байт-кода значительно различается в разных языках.

Программа на байт-коде обычно выполняется интерпретатором байт-кода (обычно он называется виртуальной машиной, поскольку подобен компьютеру). Преимущество — в портируемости, т. е. один и тот же байт-код может исполняться на разных платформах и архитектурах. То же самое преимущество дают интерпретируемые языки. Однако, поскольку байт-код обычно менее абстрактный, более компактный и более «компьютерный», чем исходный код, эффективность байт-кода обычно выше, чем чистая интерпретация исходного кода, предназначенного для правки человеком. По этой причине многие современные интерпретируемые языки на самом деле транслируют в байт-код и запускают интерпретатор байт-кода. К таким языкам относятся Perl, PHP, Ruby (начиная с версии 1.9) и Python. Программы на Java обычно передаются на целевую машину в виде байт-кода, который перед исполнением транслируется в машинный код «на лету» — с помощью JIT-компиляции. В стандарте открытых загрузчиков Open Firmware фирмы Sun Microsystems байт-код представляет операторы языка Forth.

В то же время возможно создание процессоров, для которых данный байт-код является непосредственно машинным кодом (такие процессоры существуют, например, для Java и Forth).

Также некоторый интерес представляет p-код (p-code), который похож на байт-код, но физически может быть менее лаконичным и сильно варьироваться по длине инструкции. Он работает на очень высоком уровне, например «напечатать строку» или «очистить экран». P-код повсеместно используется в СУБД и некоторых реализациях BASIC и Паскаля.

Языки и среды программирования, использующие байткод

  • Байткод Java выполняется виртуальной машиной Java (англ.  Java Virtual Machine ) выполняется виртуальной машиной FlashPlayer
  • Виртуальная машина Parrot
  • Платформа Microsoft .NET использует Intermediate Language (IL), исполняемый с помощью Common Language Runtime (CLR). См. Управляемый код.

См. также

  • Теория компиляторов

Wikimedia Foundation . 2010 .

Полезное

Смотреть что такое «Байт-код» в других словарях:

БАЙТ-КОД — Иногда используется термин псевдокод машинно независимый код низкого уровня, генерируемый транслятором и исполняемый интерпретатором (англ. byte code) Словарь бизнес терминов. Академик.ру. 2001 … Словарь бизнес-терминов

байт-код — Машинно независимый код, генерируемый Java компилятором. [ГОСТ Р 54456 2011] Тематики телевидение, радиовещание, видео EN byte codeJava byte code … Справочник технического переводчика

Байт-код Java — Байт код Java  набор инструкций, исполняемых виртуальной машиной Java. Каждый код операции байт кода  один байт. Используются не все 256 возможных значений кодов операций. 51 из них зарезервированы для использования в будущем.… … Википедия

Код (значения) — Код (фр. code, от лат. codex): В Викисловаре есть статья «код» … Википедия

Код операции — Эта статья об инструкциях; о системе команд в целом см.: Машинный код. Код операции, операционный код, опкод часть машинного языка, называемая инструкцией и определяющая операцию, которая должна быть выполнена. Определение и формат кодов… … Википедия

Байт — в запоминающих устройствах наименьшая адресуемая единица данных в памяти ЭВМ, обрабатываемая как единое целое. По умолчанию байт считается равным 8 битам. Обычно в системах кодирования данных байт представляет собой код одного печатного или… … Финансовый словарь

БАЙТ — (англ. byte) набор из стандартного числа (обычно 8) битов (двоичных единиц), используемый как единица количества информации при её передаче, хранении и обработке на ЭВМ. В международных системах кодирования данных (ASCII, EBCDIC) Б. представляет… … Юридическая энциклопедия

Промежуточный код — Байт код или байткод (англ. byte code), иногда также используется термин псевдокод машинно независимый код низкого уровня, генерируемый транслятором и исполняемый интерпретатором. Большинство инструкций байт кода эквивалентны одной или нескольким … Википедия

Байт — У этого термина существуют и другие значения, см. Byte. Байт (англ. byte)  единица хранения и обработки цифровой информации; совокупность битов, обрабатываемая компьютером одномоментно. В современных вычислительных системах байт… … Википедия

Код операции (информатика) — Эта статья об инструкциях; о системе команд в целом см.: Машинный код. В комьютерной отрасли под кодом операции (также операционный код, опкод англ. operation code) понимают часть машинного языка, называемую инструкцией, определяющую операцию,… … Википедия

Введение в байт-код Java

Каждому Java-разработчику известно, какую роль в экосистеме языка играет JVM. Однако большинство не разбирается в том, как работает JVM под капотом. Хотя для разработки на Java это не обязательно, код станет лучше, если вы глубже поймете JVM, потому что так вы будете знать, как каждая строка кода влияет на процессы внутри JVM.

Однако для начала нужно понять, что такое байт-код. Итак, поговорим о вводе и выводе байт-кода Java и о том, как он влияет на JVM во время запуска программы.

Что такое байт-код Java?

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

Байт-код — это набор команд, который JVM применяет для запуска программы. Поскольку байт-код, сгенерированный для программы, не зависит от платформы, где она запущена, вы можете без проблем запускать свою программу на любой машине, на которой есть JVM для интерпретации байт-кода.

Как генерируется байт-код?

Байт-код — это просто результат компиляции класса Java. Файл .class на самом деле представляет собой набор инструкций байт-кода, в которые преобразуется код. Он нуждается в интерпретаторе, таком как JVM, чтобы понимать и выполнять инструкции.

Как посмотреть байт-код Java?

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

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

Следующая команда позволит увидеть фактический байт-код файла .class .

Какие здесь флаги?

  • -c нужен для дизассемблирования класса Java.
  • -p нужен для раскрытия закрытых членов класса.
  • -v нужен для просмотра подробной информации, такой как размер стека и пул констант.

Как работает JVM

Прежде чем углубляться в байт-код, стоит понять, как JVM его обрабатывает.

Методы — одна из важнейших составляющих кода для JVM. Среда выполнения Java-программы — это, по сути, набор методов, вызываемых JVM. JVM создает фрейм для каждого такого метода и помещает созданный фрейм наверх стека текущего потока для выполнения.

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

Массив локальных переменных

Массив локальных переменных, как следует из названия, нужен для хранения локальных переменных в методе. Также он хранит аргументы, которые принимает метод.

В массиве локальных переменных с индексацией от нуля первые индексы используются для хранения аргументов метода. После того, как они будут сохранены, в массив сохранятся другие локальные переменные. Если метод — не статический, а создаёт экземпляры, нулевой индекс будет зарезервирован для хранения ссылки this , которая указывает на экземпляр объекта для вызова метода.

Определим два метода: один статический и один метод экземпляра, но схожие во всем остальном.

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

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

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

Инструкция байт-кода load и ее расширения нужны для перемещения значения, хранящегося в массиве переменных, в стек. Инструкция store применяется для извлечения значений из стека и сохранения в массиве переменных. Существуют и другие инструкции, которые извлекают значения из стека для обработки.

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

Посмотрим в байт-код

Ради возможности вглядеться в байт-код, я написал простой Java-класс:

Скомпилируем класс с помощью команды javac и посмотрим байт-код с помощью javap . Результат выглядит так:

Посмотрев на инструкции байт-кода, вы обнаружите несколько знакомых команд, включая load и const . Остальное, однако, может даже сбить с толку.

Деконструкция байт-кода

Все не так страшно, как кажется. Попробуем деконструировать байт-код SimpleClasсs шаг за шагом. Начнем с самого простого метода — isEven .

Вот его байт-код:

  1. Во-первых, инструкция iload_1 помещает значение массива локальных переменных с индексом 1 в стек операндов. Поскольку метод isEven является методом экземпляра, ссылка на него хранится в нулевом индексе. Тогда легко понять, что значение, хранящееся в индексе 1, на самом деле будет принятым значением параметра int .
  2. iconst_2 помещает значение 2 в верхнюю часть стека операндов.
  3. Инструкция irem применяется для нахождения остатка от деления между двумя числами. Это инструкция, которая представляет логику оператора % . Она извлекает два самых верхних значения в стеке и помещает результат обратно в стек.
  4. Команда ifne сообщает JVM перейти к инструкции с заданным смещением (в данном случае — 10), если значение, обрабатываемое командой, не равно 0. Для реализации этой логики команда берет верхний элемент стека. Если переданное число было четным, то верхний элемент будет равен 0, и в этом случае JVM получает команду перейти к инструкции с индексом 6. Однако, если значение стека не равно нулю, что происходит, когда число нечетное, JVM переходит к инструкции с индексом 10.
  5. iconst_1 помещает значение int 1 в стек. Это происходит только в том случае, если результат irem равен 1. Здесь 1 представляет логическое значение true .
  6. goto говорит JVM перейти к инструкции, приведенной в смещении, что в данном случае равно 11. Инструкция goto применяется для перехода с одного места в таблице инструкций на другое.
  7. iconst_0 помещает в стек значение 0. Эта инструкция идет в дело, когда условие if оказывается ложным. Переданное значение 0 действует как логическое значение false . Инструкции 3, 6, 7 обрабатывают случай, когда условие if истинно.
  8. ireturn возвращает значение int в верхней части стека.

Здесь важно отметить еще одно: индексы, заданные инструкциям байт-кода — как видим, они не увеличиваются на единицу для каждой новой инструкции.

Число перед инструкцией указывает на индекс ее начального байта. А любой байт-код состоит из однобайтовых опкодов, за которыми следует ноль или более операндов.

Опкоды — это такие команды, как iload , iconst и т.д. В зависимости от размера операндов размер байт-кода может варьироваться от одного байта до нескольких. Отсюда и пробелы в индексах таблицы инструкций. Единственная здесь двухбайтовая инструкция — ifne .

В байт-коде SimpleClass.class есть другие инструкции, такие как invokespecial , invokeinterface и invokestatic , которые в свою очередь являются инструкциями вызова метода.

Вывод

Надеюсь, вам удалось узнать кое-что новое о том, как работает байт-код Java. С этим более четким знанием вы сможете лучше писать код. Можете даже поэкспериментировать с самим байт-кодом во время выполнения программы, воспользовавшись такими библиотеками, как ASM.

Как объяснить, что такое байткод? [закрыт]

Хотите улучшить этот вопрос? Переформулируйте вопрос так, чтобы на него можно было дать ответ, основанный на фактах и цитатах.

Закрыт 2 года назад .

Пытался объяснить начинающим инженерам, что такое байткод (в рамках пояснения принципов выполнения Java программ). Так вот, я пытаюсь стандартно объяснить, мол это что то между компиляцией и интерпретацией, типа каждая команда джавовского байт кода, это как несколько ассемблеровских комманд, но они смотрят на меня и говорят — не понятноооо! Они не программисты, не знают что такое ни компиляция, ни интерпретация, ни ассемблер, это я попытался на пальцах им объяснить, и вроде до них что-то дошло, а как можно на пальцах используя жизненные примеры объяснит принцип работы байткода?

А нужно объяснять очень просто. Используя их положение. Для начала показываем этим инженерам программу на Java. Например, классический HelloWorld. И спрашиваем — понятно ли? Скорее всего они скажут нет. Объясняем, что и специальной программе, которая исполняет жава код, тоже не понятно. Для этого нужно «разобрать по косточкам».

Теперь делаем «псевдотрасляцию» — как для машинистки (секретарши). Для HelloWorld’а она будет такая.

  • настроить окружение (в коде этого нет, но это автоматом) — приготовить бумагу, проверить катриджи.
  • взять из памяти строку «привет мир».
  • нижимая кнопки, побуквенно ввести сроку (здесь появился цикл:) ).
  • почистить все за собой и отнести бумагу заказчику.

Формально — это и есть простой байткод. Только это человеческий байткод. А если в нем стандартизировать все операции и занумеровать, то все может быть сведено к набору чисел. Теперь к реальному байткоду перейти просто.

Легко будет объяснить и переносимость. Если человек (секретарша) выучит все коды операций, то она сможет выполнить любую работу, главное, что бы была последовательность кодов. А инженеры могут попробовать спаять-сконструировать устройство, которое будет это исполнять.

Основы Java Bytecode

Как и многие базовые вещи, на habr уже были статьи о bytecode (раз, два), основные же отличия данной статьи — в попытке визуализировать, что происходит внутри, и краткий справочник инструкций (может кому пригодится), многие с примерами использования.

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

В данной статье не рассмотрены многие темы (например, фреймы, многие атрибуты), иначе она бы получилась еще больше

Зачем знать что-то о Bytecode

Тема bytecode довольно скучная и в реальной работе среднестатистического программиста практически не используется.

Так почему стоит знать про основы bytecode:

Потому что с этим работает Java Machine и хочется понимать, что лежит в основе

Потому что многие современные фреймворки что-то тихо делают на уровне bytecode и часто могут что-то там сломать (привет, Lombok)

Потому что просто стало скучно 🙂

Как читать .class файл

Для начала вспомним, как создать .class файл. Для этого воспользуемся

Создается .class файл. Формат class файла — бинарный, файл содержит все, что нужно для выполнения программы JVM. При этом действует правило — 1 класс на 1 файл. В случае вложенных классов создаются дополнительные class файлы.

Если открыть любой class файл в hex редакторе, то файл начинается с «магических байт» — CAFEBABE, а дальше следует полезное содержимое файла.

Для того чтобы просмотреть содержимое, можно воспользоваться стандартной утилитой

javap может принимать много параметров. Давайте рассмотрим основные из них.

Смотреть будем на стандартном классе java.lang.Object

Без параметров

Выводится только основная информация по классам, методам и полям (приватные поля и методы не показываются)

Показываются также приватные поля и методы

javap -p java.lang.Object

Показываются подробную информацию (verbose), такую, как размер стека и аргументов, версии и т.д.

javap -v java.lang.Object

В IDEA имеет встроенные средства для просмотра:

Просмотр для JavaПросмотр для Java Просмотр для KotlinПросмотр для Kotlin

Что содержит .class файл

Структура .class файла (документация):

u1 , u2 , and u4 — размер полей

cp_info , field_info , method_info , attribute_info — специальные таблицы, о которых рассказывается ниже

magic — магическая константа (0xCAFEBABE), мы о ней уже говорили.

minor_version, major_version — версия формата .class файла (смотреть ниже)

constant_pool_count и constant_pool — длина пула констант и сам пул констант ( Пул констант — таблица для записи различный текстовых констант, имен интерфейсов, классов, полей и другие константы, на которые в дальнейшем будут ссылки в процессе выполнения, раздел Constant pool при выводе javap -v)

access_flags — набор флагов (public, abstract, enum и т.д.)

this_class — ссылка на пул констант, которая определяет данный класс

super_class — ссылка на пул констант, которая определяет родительский класс

interfaces_count и interfaces — количество интерфейсов, которые реализуют класс и ссылки на пул констант для этих интерфейсов

fields_count и fields — информация по полям

methods_count и methods — информация по методам

attributes_count и attributes — информация по атрибутам

Версии class файлов

Довольно часто можно увидеть ошибку, если запускать на более ранней версии jvm: Exception in thread «main» java.lang.UnsupportedClassVersionError: . has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0 . Здесь 55.0 и 52.0 — версии class файлов.

Чтобы понять, какие версии class файлов какая jvm поддерживает, можно воспользоваться таблицей из документации:

Поддерживаемые major версии

Для версии Java, начиная с 5, работает формула Major-44=Версия Java

access_flags

Flag Name (Имя флага)

public, виден за пределами пакета

final ; не может быть наследован

Обработка методов супер-класса когда вызывается инструкция invokespecial. (ссылка на более подробное объяснение)

Интерфейс, не класс

Абстрактный, не может быть наследован

Синтетический, не из кода

Модуль, не класс или интерфейс

Внутрь Bytecode

Рассмотрим первый простой файл:

javap -v -p SayHello

Версия 55.0, что соответствует версии Java 11 (55-44=11)

access_flags — ACC_PUBLIC, ACC_SUPER, так как класс публичный и при создании требуется вызвать метод суперкласса.

this_class — ссылка на имя класса ( SayHello )

super_class — ссылка на родительский класс ( java/lang/Object )

interfaces: 0, fields: 0, methods: 2, attributes: 1 — количество интерфейсов, полей, методов и атрибутов

Constant pool : — пул констант, обратите внимание, что здесь присутствуют ссылки на все методы и классы, используемые в коде, а также текст, который выводим (SayHello)

SourceFile — один из аттрибутов

Рассмотрим теперь файл с каким-нибудь полем :

Часть bytecode, касающаяся поля:

Для полей приведены флаги доступа, имя, описание (сигнатура поля) и атрибуты (здесь, ConstantValue)

Сигнатуры (descriptor) для полей имеют следующий формат:

Lимя_класса — ccылочный тип (как в примере — Ljava/lang/String)

[ — массив, например long[] будет [J

Описание структуры метода

Рассмотрим простой класс:

Выполним компиляцию с сохранением названий переменных (чтобы было легче анализировать — флаг -g ):

javac -g Main.java

Документацию можно посмотреть тут.

Descriptor — что принимает и возвращает метод. Он приводится в формате ([param1[param2[. ]]])returnValue . Для приведенного выше метода — ([Ljava/lang/String;)V .

Пример, (BB)I это int methodName(byte b1, byte b2) .

V соответствует void. Конструктор: имя = <init> , тип= (..)V . Инициализатор класса: имя= <clinit> , тип= ()V

Выполнение метода

Основы

Продолжим работать с предыдущим примером.

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

Инструкции JVM занимают 1 байт, затем следуют параметры инструкции (если они есть).

Часть инструкций привязаны к типу, с которым они работают, так например iconst_1 — работает с integer, lconst_1 — с long. Соответствие префикса от типа:

Также указывается количество ячеек для локальных переменных. (размер стека и количество локальных переменных рассчитываются компилятором). В нашем случае — 3. Первые ячейки используются для передачи параметров. Так в примере нулевая ячейка занята args (в которой записана ссылка на heap). При работе с методом класса нулевую ячейку обычно занимает ссылка на свой объект (this)

iconst_1. Кладет на стек 1.

istore_1. Снимает значение с вершины стека и записывает в локальную переменную под индексом 1

iload_1. Записывает на вершину стека значение из переменной под индексом 1.

iconst_2. Записывает на вершину стека значение 2.

iadd. Снимает с вершины стека два целых числа, суммирует их и кладет полученный результат на вершину стека

istore_2. Снимает значение с вершины стека и записывает в локальную переменную под индексом 2

getstatic #2. Находит ссылку на статическое поле указанное в пуле под индексом #2 и кладет ее на вершину стека

iload_2. Записывает на вершину стека значение из переменной под индексом 2.

invokevirtual #3. Находит метод в пуле под #3, снимает требуемое количество значений из вершины стека для использования как параметры, снимает ссылку на объект и выполняет метод. Если метод что-то возвращает, кладет обратно на вершину стека.

Как это выглядит в динамике (анимация):

Реализация if

Рассмотрим такой код:

Принятие решения выполняется в 3 строчке — if_icmple 14 . Это старый добрый условный goto и означает — возьми два значения с вершины стека и, если первое значение меньше или равно второму, перейди на 14 строчку, если нет, то продолжи выполнение дальше.

Реализация циклов

Циклы стандартно реализуются аналогично if.

Рассмотрим исходный код и его байткод:

Реализация switch

В некоторых случаях вместо набора сравнений используется более быстрый механизм — lookupswitch или tableswitch (lookupswitch использует таблицу переходов с ключами и метками куда переходить, tableswitch — используется таблицу только с метками).

Реализация throw

При выполнении он выведет:

строчки 1-4 — создание объекта исключения,

athrow — выброс этого исключения.

Здесь добавилась Exception table, в которой строки отсортированы таким образом, что виртуальная машина проверяет соответствие строки и вида исключения сверху вниз с последней точки, где она остановилась.

Когда мы дошли до 9 строчки, виртуальная машина выбросила исключение. И начала смотреть в Exception table. Первая запись удовлетворяет условиям использования (строчка 9 находится в интервале от 0 до 10 и указан RuntimeException) и поэтому выполняется переход на строчку 10.

Дальше мы доходим до строчки 31 и снова выполняется выброс исключения. Смотреть мы теперь начинаем с 2 строчки ExceptionTable. Она нам не подходит и поэтому переходим на 3, которая подходит, и выполняем переход на 32 строчку.

Вызовы методов (opcode: invokestatic, invokespecial, invokevirtual, invokeinterface, invokedynamic)

invokestatic

Используется для вызова статического метода. (Используется статическое связывание /Static Dispatch)

invokespecial

Используется для прямого вызова методов объекта текущего класса, конструкторов и методов родительского класса (Используется статическое связывание/Static Dispatch).

При этом первым параметром передается ссылка на объект.

javap -p -v Main$Son

Bytecode для конструктора класса Son

invokevirtual

Используется для вызова методов класса, при этом используется динамический поиск какой метод вызывать, основываясь на классе (Dynamic Dispatch). Так как методы могут быть переопределены, то сначала проверяется наличие метода в переданном классе, потом в родительском и так далее. Для поиска в HotSpot используется специальная таблица методов. Подробности можно посмотреть тут. При этом первым параметром передается ссылка на объект.

Немного изменим предыдущий пример

Bytecode для конструктора класса Son

Теперь в строчках 5 и 10 используется invokevirtual.

invokeinterface

Используется для вызова методов интерфейса (Dynamic Dispatch). При этом первым параметром передается ссылка на объект.

На 9 строчке вызывается метод интерфейса

invokedynamic

Вызов динамически-вычисляемых call sites. Сейчас, например, используется в Java для создания объектов для лямбд. Описание, как работает данный opcode, займет не одну статью и лучше всего посмотреть тут

Справочник основных opcode

Полная и единственно достоверная информация находится на сайте Oracle.

Здесь и далее сначала приводится мнемоническое название (mnemonic), потом код действия (opcode), дальше приводится состояние стека до выполнения команды, на следующей строчке — после выполнения команды, дальше, если требуется, формат команды, краткое описание на русском и пример кода, где встречается эта команда

aaload (0x32) , baload (0x33), caload (0x34), daload (0x31), iaload (0x2e), faload (0x30), laload (0x2f), saload (0x35)

Загрузка ссылки из массива (a* — ссылок, b* — byte или boolean, c* — char, d* — double, i* — integer, f* — float, l* — long, s* — short)

aastore (0x53) , bastore (0x54), castore (0x55), dastore (0x52), iastore (0x4а), fastore (0x51), lastore (0x50), sastore (0x56)

Записать элемент в массив (a* — ссылок, b* — byte или boolean, c* — char, d* — double, i* — integer, f* — float, l* — long, s* — short)

aconst_null (0x1)

Положить на стек null

aload (0x30) , dload (0x18), iload (0x15), fload (0x17), lload (0x16)

Формат: dload index

Загрузить значение из локальной переменной под индекcом index (a* — ссылок, d* — double, i* — integer, f* — float, l* — long).

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *