Байт-код Java
Байт-код Java — это набор инструкций виртуальной машины Java (JVM), языка, на котором и другой JVM-совместимый исходный код Java компилируется . [1] Каждая инструкция представлена одним байтом , отсюда и название байт-код , что делает ее компактной формой данных . [2]
Из-за природы байт-кода программу с байт-кодом Java можно запустить на любой машине с совместимой JVM; без длительного процесса компиляции из исходного кода.
Байт-код Java используется во время выполнения либо интерпретируется JVM, либо компилируется в машинный код посредством JIT -компиляции и запускается как собственное приложение.
Поскольку байт-код Java разработан с учетом кросс-платформенной совместимости и безопасности, приложение с байт-кодом Java имеет тенденцию одинаково работать в различных конфигурациях оборудования и программного обеспечения . [3]
Отношение к Java
[ редактировать ]В общем, Java- программисту не обязательно понимать байт-код Java или даже знать о нем. Однако, как говорится в журнале IBM DeveloperWorks: «Понимание байт-кода и того, какой байт-код может быть сгенерирован компилятором Java, помогает программисту Java так же, как знание ассемблера помогает программисту C или C++ ». [4]
Архитектура набора команд
[ редактировать ]Байт-код включает в себя различные типы инструкций, включая манипулирование данными, передачу управления, создание и манипулирование объектами, а также вызов методов, которые являются неотъемлемой частью модели объектно-ориентированного программирования Java. [1]
JVM является одновременно стековой машиной и регистровой машиной . Каждый кадр вызова метода имеет «стек операндов» и массив «локальных переменных». [5] : 2.6 [2] Стек операндов используется для операндов вычислений и для получения возвращаемого значения вызываемого метода, а локальные переменные служат той же цели, что и регистры , а также используются для передачи аргументов метода. Максимальный размер стека операндов и массива локальных переменных, вычисленный компилятором, является частью атрибутов каждого метода. [5] : 4.7.3 Каждый из них может иметь независимый размер от 0 до 65535 значений, где каждое значение имеет длину 32 бита. long
и double
типы, которые являются 64-битными, занимают две последовательные локальные переменные [5] : 2.6.1 (которые не обязательно должны быть выровнены по 64 битам в массиве локальных переменных) или одно значение в стеке операндов (но считаются как две единицы глубины стека). [5] : 2.6.2
Набор инструкций
[ редактировать ]Каждый байт-код состоит из одного байта, представляющего код операции , а также нуля или более байтов для операндов. [5] : 2.11
Из 256 возможных кодов операций длиной в байт , по состоянию на 2015 год [update], 202 используются (~79%), 51 зарезервированы для использования в будущем (~20%) и 3 инструкции (~1%) постоянно зарезервированы для использования реализациями JVM. [5] : 6.2 Два из них ( impdep1
и impdep2
) должны предоставлять ловушки для программного и аппаратного обеспечения, специфичного для реализации, соответственно. Третий используется отладчиками для реализации точек останова.
Инструкции делятся на несколько широких групп:
- Загрузите и сохраните (например,
aload_0
,istore
) - Арифметика и логика (например,
ladd
,fcmpl
) - Преобразование типов (например
i2b
,d2i
) - Создание и манипулирование объектами (
new
,putfield
) - Управление стеком операндов (например,
swap
,dup2
) - Передача управления (например,
ifeq
,goto
) - Вызов метода и возврат (например,
invokespecial
,areturn
)
Есть также несколько инструкций для ряда более специализированных задач, таких как выдача исключений, синхронизация и т. д.
Многие инструкции имеют префиксы и/или суффиксы, относящиеся к типам операндов, с которыми они работают. [5] : 2.11.1 Они заключаются в следующем:
Префикс/суффикс | Тип операнда |
---|---|
i |
целое число |
l |
длинный |
s |
короткий |
b |
байт |
c |
характер |
f |
плавать |
d |
двойной |
a |
ссылка |
Например, iadd
добавит два целых числа, а dadd
добавит два дубля. const
, load
, и store
инструкции также могут иметь суффикс формы _n
, где n — число от 0 до 3 для load
и store
. Максимальное n для const
различается по типу.
The const
инструкции помещают значение указанного типа в стек. Например, iconst_5
поместит целое число (32-битное значение) со значением 5 в стек, а dconst_1
поместит в стек двойное значение (64-битное значение с плавающей запятой) со значением 1. Существует также aconst_null
, что подталкивает null
ссылка. n для load
и store
инструкции указывают индекс в массиве локальных переменных для загрузки или сохранения. aload_0
Инструкция помещает объект из локальной переменной 0 в стек (обычно это this
объект). istore_1
сохраняет целое число на вершине стека в локальную переменную 1. Для локальных переменных после 3 суффикс отбрасывается и необходимо использовать операнды.
Пример
[ редактировать ]Рассмотрим следующий код Java:
outer:
for (int i = 2; i < 1000; i++) {
for (int j = 2; j < i; j++) {
if (i % j == 0)
continue outer;
}
System.out.println (i);
}
Компилятор Java может преобразовать приведенный выше код Java в байт-код следующим образом, предполагая, что приведенное выше было помещено в метод:
0: iconst_2
1: istore_1
2: iload_1
3: sipush 1000
6: if_icmpge 44
9: iconst_2
10: istore_2
11: iload_2
12: iload_1
13: if_icmpge 31
16: iload_1
17: iload_2
18: irem
19: ifne 25
22: goto 38
25: iinc 2, 1
28: goto 11
31: getstatic #84; // Field java/lang/System.out:Ljava/io/PrintStream;
34: iload_1
35: invokevirtual #85; // Method java/io/PrintStream.println:(I)V
38: iinc 1, 1
41: goto 2
44: return
Поколение
[ редактировать ]Наиболее распространенным языком, предназначенным для виртуальной машины Java для создания байт-кода Java, является Java. Первоначально существовал только один компилятор — компилятор javac от Sun Microsystems , который компилирует исходный код Java в байт-код Java; но поскольку все спецификации байт-кода Java теперь доступны, другие стороны предоставили компиляторы, которые создают байт-код Java. Примеры других компиляторов включают:
- Компилятор Eclipse для Java (ECJ)
- Jikes , компилирует из Java в байт-код Java (разработан IBM , реализован на C++ ).
- Espresso, компилируется из Java в байт-код Java (только Java 1.0).
- Компилятор GNU для Java (GCJ) компилирует из Java в байт-код Java; он также может компилироваться в собственный машинный код и был частью коллекции компиляторов GNU (GCC) до версии 6.
Некоторые проекты предоставляют ассемблеры Java, позволяющие писать байт-код Java вручную. Ассемблерный код также может быть сгенерирован машиной, например, компилятором, предназначенным для виртуальной машины Java . Известные ассемблеры Java включают:
- Jasmin принимает текстовые описания классов Java, написанные с использованием простого синтаксиса, подобного ассемблеру, с использованием набора инструкций виртуальной машины Java, и генерирует файл класса Java. [6]
- Ямайка — макросов язык на ассемблере для виртуальной машины Java . Синтаксис Java используется для определения класса или интерфейса. Тела методов указываются с помощью инструкций байт-кода. [7]
- Krakatau Bytecode Tools в настоящее время содержит три инструмента: декомпилятор и дизассемблер для файлов классов Java и ассемблер для создания файлов классов. [8]
- Lilac — ассемблер и дизассемблер виртуальной машины Java . [9]
Другие разработали компиляторы для разных языков программирования для виртуальной машины Java, например:
- КолдФьюжн
- JRuby и Jython , два языка сценариев, основанные на Ruby и Python.
- Apache Groovy , опционально типизированный и динамический язык общего назначения с возможностями статической типизации и статической компиляции.
- Scala — типизированный язык программирования общего назначения, поддерживающий объектно-ориентированное и функциональное программирование.
- JGNAT и AppletMagic, компилируют язык Ada в байт-код Java.
- Компиляторы байт-кода C в Java [ мертвая ссылка ]
- Clojure — функциональный, неизменяемый язык программирования общего назначения из семейства Lisp с сильным упором на параллелизм.
- Kawa — реализация языка программирования Scheme , также диалекта Lisp .
- МидлетПаскаль
- Код JavaFX Script компилируется в байт-код Java.
- Kotlin — статически типизированный язык программирования общего назначения с выводом типа.
- Исходный код Object Pascal компилируется в байт-код Java с помощью компилятора Free Pascal 3.0+. [10] [11]
Исполнение
[ редактировать ]Сегодня доступно несколько виртуальных машин Java для выполнения байт-кода Java, как бесплатных, так и коммерческих продуктов. Если выполнение байт-кода на виртуальной машине нежелательно, разработчик может также скомпилировать исходный код Java или байт-код непосредственно в машинный код с помощью таких инструментов, как компилятор GNU для Java (GCJ). Некоторые процессоры могут самостоятельно выполнять байт-код Java. Такие процессоры называются процессорами Java .
Поддержка динамических языков
[ редактировать ]Виртуальная машина Java обеспечивает некоторую поддержку динамически типизированных языков . Большая часть существующего набора инструкций JVM статически типизирована - в том смысле, что сигнатуры вызовов методов проверяются по типу во время компиляции , без механизма, позволяющего отложить это решение до времени выполнения или выбрать отправку метода альтернативным подходом. [12]
JSR 292 ( Поддержка динамически типизированных языков на платформе Java ) [13] добавил новый invokedynamic
инструкции на уровне JVM, чтобы разрешить вызов метода, основанный на динамической проверке типа (вместо существующей статической проверки типа). invokevirtual
инструкция). Da Vinci Machine — это реализация прототипа виртуальной машины, на которой размещены расширения JVM, предназначенные для поддержки динамических языков. Все JVM, поддерживающие JSE 7, также включают в себя invokedynamic
код операции.
См. также
[ редактировать ]- Инженерная библиотека байт-кода
- Common Intermediate Language (CIL), конкурент Microsoft байт-коду Java.
- Инструменты резервного копирования Java
- Файл класса Java
- виртуальная машина Java
- ДжейСтик
- ОбъектВеб ASM
Ссылки
[ редактировать ]- ^ Jump up to: а б «Спецификация виртуальной машины Java» . Оракул . Проверено 14 ноября 2023 г.
- ^ Jump up to: а б Линдхольм, Тим (2015). Спецификация виртуальной машины Java . Оракул. ISBN 978-0133905908 .
- ^ Арнольд, Кен (1996). «Язык программирования Java». Сан Микросистемс . 1 (1): 30–40.
- ^ «Разработчик IBM» . разработчик.ibm.com . Проверено 20 февраля 2006 г.
- ^ Jump up to: а б с д и ж г Линдхольм, Тим; Йеллин, Фрэнк; Браха, Гилад; Бакли, Алекс (13 февраля 2015 г.). Спецификация виртуальной машины Java (Java SE 8-е изд.).
- ^ «Домашняя страница Жасмин» . jasmin.sourceforge.net . Проверено 2 июня 2024 г.
- ^ «Ямайка: ассемблер макросов виртуальной машины Java (JVM)» . Проверено 2 июня 2024 г.
- ^ «Сказочник/Кракатау» . 1 июня 2024 г. Получено 2 июня 2024 г. - через GitHub.
- ^ «Сирень — ассемблер Java» . lilac.sourceforge.net . Проверено 2 июня 2024 г.
- ^ «Новые возможности FPC 3.0.0 — бесплатная вики по Pascal» . wiki.freepascal.org . Проверено 2 июня 2024 г.
- ^ «FPC JVM — Free Pascal wiki» . wiki.freepascal.org . Проверено 2 июня 2024 г.
- ^ Наттер, Чарльз (3 января 2007 г.). «InvokeDynamic: действительно полезно?» . Проверено 25 января 2008 г.
- ^ «Программа Java Community Process (SM) — JSR: запросы спецификаций Java — подробно JSR № 292» . www.jcp.org . Проверено 2 июня 2024 г.
Внешние ссылки
[ редактировать ]- Спецификация виртуальной машины Oracle Java
- Языки программирования для виртуальной машины Java
- Bytecode Visualizer – просмотрщик и отладчик байт-кода (бесплатный плагин Eclipse)
- AdaptJ StackTrace — отладка на уровне байт-кода с полным контролем над стеком, локальными переменными и потоком выполнения.
- Java Class Unpacker – плагин для Total Commander, позволяет открывать файлы классов в виде сжатых архивов и просматривать поля и методы в виде файлов. Байт-код можно просмотреть как текст с помощью F3.