Java байт - код является набором команд из виртуальной машины Java (JVM).
Отношение к Java [ править ]
Программисту Java совсем не нужно знать или понимать байт-код Java. Однако, как написано в журнале IBM developerWorks: «Понимание байт-кода и того, какой байт-код может быть сгенерирован компилятором Java, помогает программисту Java так же, как знание сборки помогает программисту на C или C ++ ». [1]
Архитектура набора команд [ править ]
JVM является одновременно стековой и регистровой машиной . Каждый кадр для вызова метода имеет «стек операндов» и массив «локальных переменных». [2] : 2.6 Стек операндов используется для операндов для вычислений и для получения возвращаемого значения вызываемого метода, в то время как локальные переменные служат той же цели, что и регистры, и также используются для передачи аргументов метода. Максимальный размер стека операндов и массива локальных переменных, вычисляемый компилятором, является частью атрибутов каждого метода. [2] : 4.7.3 Каждое значение может иметь независимый размер от 0 до 65 535, где каждое значение составляет 32 бита. long
иdouble
типы, которые являются 64 -битными , занимают две последовательные локальные переменные [2] : 2.6.1 (которые не должны быть выровнены по 64-битным в массиве локальных переменных) или одно значение в стеке операндов (но считаются как две единицы в глубина стопки). [2] : 2.6.2
Набор инструкций [ править ]
Каждый байт-код состоит из одного байта, который представляет код операции , а также нуля или более байтов для операндов. [2] : 2,11
Из 256 возможных кодов операций длиной в байт по состоянию на 2015 год [Обновить]202 используются (~ 79%), 51 зарезервированы для будущего использования (~ 20%), а 3 инструкции (~ 1%) постоянно зарезервированы для реализаций JVM для использовать. [2] : 6.2 Два из них ( impdep1
и impdep2
) должны обеспечивать ловушки для программного и аппаратного обеспечения, зависящего от реализации, соответственно. Третий используется отладчиками для реализации точек останова.
Инструкции делятся на несколько широких групп:
- Загрузить и сохранить (например
aload_0
,istore
) - Арифметика и логика (например
ladd
,fcmpl
) - Преобразование типа (например
i2b
,d2i
) - Создание и управление объектами (
new
,putfield
) - Управление стеком операндов (например
swap
,dup2
) - Передача управления (например
ifeq
,goto
) - Вызов и возврат метода (например
invokespecial
,areturn
)
Также есть несколько инструкций для ряда более специализированных задач, таких как генерация исключений, синхронизация и т. Д.
Многие инструкции имеют префиксы и / или суффиксы, относящиеся к типам операндов, с которыми они работают. [2] : 2.11.1 Это следующие:
Префикс Суффикс | Тип операнда |
---|---|
i | целое число |
l | длинная |
s | короткая |
b | байт |
c | символ |
f | плавать |
d | двойной |
a | Справка |
Например, iadd
добавит два целых числа, а dadd
два - двойных. const
, load
И store
инструкции могут также принимать суффикс формы , где п представляет собой число от 0-3 для и . Максимальный п для различена по типу._n
load
store
const
В const
инструкции нажать значение указанного типа в стек. Например, iconst_5
поместит в стек целое число (32-битное значение) со значением 5, а dconst_1
двойное (64-битное значение с плавающей запятой) со значением 1 в стек. Также есть aconst_null
, который подталкивает null
ссылку. П для load
и store
инструкции определяет индекс в массиве локальной переменной к нагрузке от или магазина к. aload_0
Инструкция толкает объект в локальной переменной 0 на стек (обычно это this
объект). istore_1
сохраняет целое число наверху стека в локальную переменную 1. Для локальных переменных, превышающих 3, суффикс отбрасывается, и должны использоваться операнды.
Пример [ править ]
Рассмотрим следующий код Java:
внешний: for ( int i = 2 ; i < 1000 ; i ++ ) { for ( int j = 2 ; j < i ; j ++ ) { if ( i % j == 0 ) continue external ; } Система . из . println ( я ); }
Компилятор 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; // Поле java / lang / System.out : Ljava / io / PrintStream; 34 : iload_1 35 : invokevirtual # 85 ; // Метод 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 Compiler for Java (GCJ), компилирует из Java в байт-код Java; он также может компилироваться в собственный машинный код и был частью коллекции компиляторов GNU (GCC) до версии 6.
Некоторые проекты предоставляют ассемблеры Java, позволяющие писать байт-код Java вручную. Ассемблерный код также может быть сгенерирован машиной, например компилятором, нацеленным на виртуальную машину Java . Известные ассемблеры Java включают:
- Jasmin принимает текстовые описания для классов Java, написанные в простом синтаксисе, подобном ассемблере, с использованием набора команд виртуальной машины Java и генерирует файл классов Java [3]
- Ямайка, язык макроса ассемблера для виртуальной машины Java . Синтаксис Java используется для определения класса или интерфейса. Тела методов указываются с помощью инструкций байт-кода. [4]
- Krakatau Bytecode Tools в настоящее время содержит три инструмента: декомпилятор и дизассемблер для файлов классов Java и ассемблер для создания файлов классов. [5]
- Lilac, ассемблер и дизассемблер для виртуальной машины Java . [6]
Другие разработали компиляторы для разных языков программирования для виртуальной машины Java, например:
- Холодный синтез
- JRuby и Jython , два языка сценариев, основанные на Ruby и Python
- Apache Groovy , необязательно типизированный и динамический язык общего назначения с возможностями статической типизации и статической компиляции
- Scala , типобезопасный язык программирования общего назначения, поддерживающий объектно-ориентированное и функциональное программирование.
- JGNAT и AppletMagic, компилируют с языка Ada в байт-код Java
- Компиляторы байтового кода C в Java [ мертвая ссылка ]
- Clojure , функциональный неизменяемый язык программирования общего назначения из семейства Lisp с упором на параллелизм.
- Kawa , реализация языка программирования Scheme , также являющегося диалектом Lisp .
- MIDletPascal
- Код JavaFX Script компилируется в байт-код Java
- Kotlin , статически типизированный язык программирования общего назначения с выводом типа
- Исходный код Object Pascal компилируется в байт-код Java с помощью компилятора Free Pascal 3.0+. [7] [8]
Казнь [ править ]
Сегодня доступно несколько машин, как бесплатных, так и коммерческих.
Если выполнение байт-кода Java на виртуальной машине Java нежелательно, разработчик также может скомпилировать исходный код Java или байт-код непосредственно в машинный код с помощью таких инструментов, как GNU Compiler for Java (GCJ). Некоторые процессоры могут выполнять байт-код Java изначально. Такие процессоры называются процессорами Java .
Поддержка динамических языков [ править ]
Виртуальная машина Java обеспечивает некоторую поддержку для динамически типизированных языков . Большая часть существующего набора инструкций JVM является статически типизированной - в том смысле, что сигнатуры вызовов методов проверяются во время компиляции , без механизма, чтобы отложить это решение до времени выполнения или выбрать отправку метода с помощью альтернативного подхода. [9]
JSR 292 ( Поддержка динамически типизированных языков на платформе Java ) [10] добавил новую invokedynamic
инструкцию на уровне JVM, чтобы разрешить вызов метода, основанного на динамической проверке типа (вместо существующей invokevirtual
инструкции статической проверки типа ). Vinci Machine Da является прообразом реализации виртуальной машины , что хосты JVM расширений , направленных на поддержку языков динамических. Все JVM, поддерживающие JSE 7, также включают invokedynamic
код операции.
См. Также [ править ]
- Списки инструкций по байт-коду Java
- Файл класса Java
- Список языков JVM
- Инструменты резервного копирования Java
- Компиляторы виртуальных машин C в Java
- JStik
- Common Intermediate Language (CIL), соперник Microsoft для байт-кода Java
- ObjectWeb ASM
- Инженерная библиотека байтового кода
Ссылки [ править ]
- ^ Понимание байт-кода делает вас лучшим программистом
- ^ Б с д е е г Линдхольма, Tim; Йеллин, Франк; Браха, Гилад; Бакли, Алекс (13 февраля 2015). Спецификация виртуальной машины Java (Java SE 8 ed.).
- ^ Домашняя страница Jasmin
- ^ Ямайка: ассемблер макросов виртуальной машины Java (JVM)
- ^ Домашняя страница Krakatau
- ^ Домашняя страница Lilac
- ^ Примечания к выпуску Free Pascal 3.0
- ^ Цель Free Pascal JVM
- ^ Наттер, Чарльз (2007-01-03). "InvokeDynamic: Действительно полезно?" . Проверено 25 января 2008 .
- ^ см. JSR 292
Внешние ссылки [ править ]
В Викиуке по программированию на Java есть страница по теме: Байт-код Java. |
- Спецификация виртуальной машины Oracle Java
- Языки программирования для виртуальной машины Java
- Визуализатор байт-кода - просмотрщик и отладчик байт-кода (бесплатный плагин Eclipse)
- AdaptJ StackTrace - отладка на уровне байт-кода с полным контролем над стеком, локальными переменными и потоком выполнения
- Java Class Unpacker - плагин для Total Commander, он позволяет открывать файлы классов как сжатые архивы и видеть поля и методы как файлы. Байт-код можно просмотреть как текст с помощью F3.