Байт-код Java — набор инструкций, исполняемых виртуальной машиной Java. Каждый код операции байт-кода — один байт; используются не все 256 возможных значений кодов операций, 51 из них зарезервирован для использования в будущем.
Для программирования на языке Java или других JVM-совместимых языках знание особенностей байт-кода не обязательно, тем не менее, «понимание байт-кода и понимание механизмов его генерации компилятором Java помогает Java-программисту так же, как и знание языка ассемблера помогает программисту, пишущему на Си или C++»[1][2].
Инструкции
правитьКод CA16 зарезервирован для использования отладчиком и не используется языком, как и коды FE16 и FF16, которые зарезервированы для использования виртуальной машиной и отладчиками. Коды в диапазоне CB16—FD16 в текущей версии JVM не используются и зарезервированы для будущих дополнений.
Инструкции можно разделить на несколько групп:
- загрузка и сохранение (например, ALOAD_0, ISTORE),
- арифметические и логические операции (например, IADD, FCMPL),
- преобразование типов (например, I2B, D2I),
- создание и преобразование объекта (например, NEW, PUTFIELD),
- управление стеком (например, DUP, POP),
- операторы перехода (например, GOTO, IFEQ),
- вызовы методов и возврат (например, INVOKESTATIC, IRETURN).
Также есть несколько инструкций, выполняющих специфические задачи, такие как выбрасывание исключений, синхронизация и так далее.
Многие инструкции имеют префиксы или суффиксы, соответствующие их операндам:
Префикс или суффикс | Тип операнда |
---|---|
I |
integer |
L |
long |
S |
short |
B |
byte |
C |
character |
F |
float |
D |
double |
A |
reference |
Например, операция IADD — сложение двух целых чисел, в то время как FADD — сложение чисел с плавающей точкой.
Пример
правитьКод на языке 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);
}
компилятор может транслировать в следующий байт-код:
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. Единственный оригинальный компилятор, преобразующий код на языке Java в байт-код Java — это Javac, созданный компанией Sun Microsystems. Но поскольку все спецификации байт-кода Java доступны, существуют и сторонние компиляторы, генерирующие этот байт-код. Примеры таких компиляторов:
- Jikes[англ.] — компилирует код на Java в Java-байт-код (разработан IBM, написан на C++),
- Espresso — компилирует код на Java в Java-байт-код (для версии Java 1.0),
- GCJ (GNU Compiler for Java) — компилирует код на Java в Java-байт-код, также способен компилировать в нативный машинный код, является частью GNU Compiler Collection.
Для некоторых проектов существуют компиляторы, позволяющие генерировать байт-код для JVM из исходного кода на другом языке программирования, среди таких проектов:
- ColdFusion,
- JRuby и Jython (для Ruby и Python соответственно),
- Groovy (скриптовый язык, основанный на Java),
- Scala,
- Kotlin,
- JGNAT и AppletMagic,
- компиляторы с языка Си в Java-байт-код,
- Clojure,
- MIDletPascal,
- JavaFX Script.
Большинство существующих инструкций JVM имеет статическую типизацию: сигнатуры методов в местах их вызова проверяются во время компиляции, но механизм переноса этой проверки на время выполнения отсутствует[3]. Тем не менее, для JVM реализован ряд языков с динамической типизацией.
Примечания
править- ↑ Peter Haggar, Understanding bytecode makes you a better programmer Архивная копия от 8 декабря 2008 на Wayback Machine // IBM DeveloperWorks, 01 Jul 2001
- ↑ A Formal Introduction to the Compilation of Java, Stephan Diehl, «Software — Practice and Experience», Vol. 28(3), pages 297—327, March 1998. Дата обращения: 25 апреля 2013. Архивировано 25 мая 2013 года.
- ↑ Nutter, Charles InvokeDynamic: Actually Useful? (3 января 2007). Дата обращения: 25 января 2008. Архивировано 30 апреля 2013 года.