Kod bajtowy Javy
Kod bajtowy Javy – lista instrukcji do wykonania przez wirtualną maszynę Javy (JVM). Każdy kod operacji kodu bajtowego ma jeden bajt długości, chociaż niektóre kody operacji wymagają parametrów, co sprawia, że mamy dużo wielobajtowych instrukcji. Nigdy nie użyto wszystkich możliwych 256 kodów operacyjnych.
Związek z językiem Java
edytujProgramista języka Java w rzeczywistości nie musi wiedzieć, jak działa kod bajtowy Javy. Jednak w piśmie IBM developerWorks zasugerowano: „Znajomość kodu bajtowego Javy pomaga programiście tak, jak znajomość asemblera pomaga programistom języków C i C ”[1].
Instrukcje
edytujKażdy bajt może mieć 256 różnych wartości. Spośród nich w 0x00 przez 0xca, 0xfe, i 0xff są przypisane wartości. 0xba jest nieużywany z powodów historycznych. 0xca jest zarezerwowany jako instrukcja przerwania dla debuggerów i nie jest używany w języku. Podobnie 0xfe i 0xff nie są używane, gdyż zarezerwowane są do wewnętrznego użytku maszyny wirtualnej.
Instrukcje można podzielić na następujące grupy:
- ładujące i zapisujące (np. aload_0, istore),
- arytmetyczne i logiczne (np. ladd, fcmpl),
- zmieniające typ (np. i2b, d2i),
- tworzące obiekt i manipulujące nim (np. new, putfield),
- przenoszące sterowanie (np. ifeq, goto),
- wywołujące metodę i wracające z niej (np. invokespecial, areturn).
Jest też kilka instrukcji służących do bardziej wyspecjalizowanych czynności, np. zwracanie wyjątków, synchronizacja itd.
Duża część instrukcji ma też prefiksy lub sufiksy związane z typami zmiennych, na których pracują. Oto ich lista:
Prefiks/Sufiks | Typ w języku Java | Opis | Przyjmowane wartości |
---|---|---|---|
i |
int |
32-bitowy typ całkowity ze znakiem | -231 .. 231-1
|
l |
long |
64-bitowy typ całkowity ze znakiem | -263 .. 263-1
|
s |
short |
16-bitowy typ całkowity ze znakiem | -215 .. 215-1
|
b |
byte |
8-bitowy typ całkowity ze znakiem | -128 .. 127
|
c |
char |
16-bitowy typ całkowity bez znaku | 0 .. 65 535
|
f |
float |
32-bitowy typ zmiennoprzecinkowy | N/A |
d |
double |
64-bitowy typ zmiennoprzecinkowy | N/A |
z |
boolean |
1-bitowy typ Booleanowski | 0 lub 1
|
a |
Object i pochodne |
Referencja do instancji klasy Object |
N/A |
Na przykład, ladd dodaje do siebie dwie zmienne typu long, a sadd dwie zmienne typu short. Instrukcje „const”, „load” i „store” mogą ponadto posiadać sufiks wyglądający tak: „_n”, z tym, że w miejscu n podstawiamy liczbę od 0-3 dla instrukcji „load” i „store”. Największe możliwe n dla instrukcji „const” zależne jest od typu, na którym pracuje.
Model obliczeń
edytujDla przykładu, kod asemblera dla procesora x86 mógłby wyglądać tak:
add eax, edx
mov ecx, eax
Ten kod dodaje dwie liczby do siebie, a następnie przenosi je w inne miejsce. Robiący to samo kod bajtowy Javy wyglądałby następująco:
0 iload_1 1 iload_2 2 iadd 3 istore_3
W tym kodzie, dwie wartości które zostaną do siebie dodane umieszczane są na stosie, gdzie są pobierane przez instrukcję która je dodaje i wynik umieszcza na stosie. Instrukcja przechowywania następnie przenosi je do najwyższej wartości na obszarze stosu w lokacji zmiennej. Liczby przed instrukcjami to po prostu przesunięcie każdej instrukcji od początku metody. Metoda nazwana np. „pobierzNazwe()” mogłaby wyglądać tak:
Method java.lang.String pobierzNazwe() 0 aload_0 // Obiekt „this” jest zapisywany w lokacji 0 tabeli zmiennych 1 getfield #5 <Field java.lang.String nazwa> // Instrukcja ta pobiera obiekt z wierzchu stosu, zwraca wybrane // pole z niego i umieszcza je na stosie. // W tym przykładzie, pole o nazwie „nazwa” jest piątym polem klasy 4 areturn // Zwraca obiekt na szczycie stosu z metody.
Przykład
edytujPrzykład kodu w Javie, źródło:
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);
}
Kompilator Javy generuje następujący kod bajtowy:
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
Generowanie kodu
edytujNajczęściej spotykanym językiem tworzący kod bajtowy Javy jest Java. Jest jeden oficjalny kompilator Javy, javac firmy Sun Microsystems, który kompiluje kod źródłowy Javy do kodu bajtowego Javy. Jednakże specyfikacja kodu bajtowego Javy jest ogólnodostępna, co sprawiło, że powstały kompilatory przystosowane do innych języków programowania.
Uruchamianie kodu
edytujKod bajtowy Javy zaprojektowany został, aby go uruchamiać na wirtualnej maszynie Javy.
Aby wygenerować kod maszynowy, można użyć aplikacji GCJ z pakietu GNU Compiler Collection.
Obsługa języków dynamicznych
edytujJVM obecnie nie ma wbudowanej obsługi języków o dynamicznym systemie typów. Ponieważ istniejący zestaw instrukcji dla JVM jest w statycznym systemie typów, co oznacza, że wywołania metod mają przypisane sygnatury typów sprawdzane podczas kompilacji, bez mechanizmu odraczania sprawdzania do czasu uruchomienia kodu lub wybrania metody wysyłki przez alternatywny typ[2].
JSR 292 Supporting Dynamically Typed Languages on the JavaTM Platform (z ang. Obsługa języków o dynamicznym systemie typów na platformie JavaTM)[3] dodaje nową instrukcję invokedynamic
, która umożliwia wywołanie metody opierając się na dynamicznym sprawdzaniu typów (zamiast istniejącej funkcji invokevirtual
, która opiera się na statycznym sprawdzaniu typów).
Lista języków kompilowanych do kodu bajtowego Javy
edytujImplementacje istniejących języków
edytujJęzyk | Implementacje |
---|---|
Ada | JGNAT AdaMagic |
AWK | Jawk[4] |
C | NestedVM, Cibyl, LLJVM, AMPC[5] |
Cobol | Micro Focus JVM Visual COBOL[6] Veryant isCobol[7] |
ColdFusion | Adobe ColdFusion Railo Open BlueDragon |
Common Lisp | Armed Bear Common Lisp[8] CLforJava Jatha |
Component Pascal | Gardens Point Component Pascal |
Erlang | Erjang[9] |
Forth | myForth[10] |
JavaScript | Rhino |
LOGO | jLogo[11] XLogo[12] |
Lua | Kahlua[13] Luaj[14] Jill[15] |
Oberon-2 | Canterbury Oberon-2 for JVM |
OCaml | OCaml-Java[16] |
Pascal | Canterbury Pascal for JVM |
PHP | IBM WebSphere sMash PHP (P8)[17] Caucho Quercus[18] |
Python | Jython |
Perl6 | Perl6 |
Rexx | IBM NetRexx |
Ruby | JRuby |
Scheme | Bigloo Kawa SISC JScheme |
Tcl | Jacl JTcl[19] |
Języki zaprojektowane dla kompilacji do kodu bajtowego Javy
edytuj- Alef [20], język programowania zainspirowany językami Perl i Lisp,
- Ateji PX[21],
- BBj, obiektowy język programowania zaprojektowany do pisania aplikacji biznesowych,
- BeanShell, język skryptowy podobny w składni do Javy,
- Ceylon,
- ColdFusion, język skryptowy używany na serwerze aplikacji ColdFusion,
- CAL, zainspirowany językiem Haskell funkcjonalny język programowania,
- kod języka E może być kompilowany do kodu bajtowego Javy,
- Fantom[22],
- Flow Java,
- Fortress, język zaprojektowany przez Sun, jako następca dla języka Fortran,
- Frink,
- Gosu, rozszerzalny język, którego kod jest kompilowany do kodu bajtowego Javy,
- Hecl[23],
- Ioke, język przypominający język Io, z podobieństwami do języka Ruby, Lisp i Smalltalk,
- KBML,
- Jabaco,
- Jaskell[24], inspirowany językiem Haskell,
- Jelly,
- Join Java, język będący pochodną Javy,
- Joy,
- Judoscript,
- Mirah[25], język programowania ze składnią przypominającą Ruby,
- N.A.M.E. Basic,
- NetLogo,
- Nice,
- Noop,
- ObjectScript,
- PHP.reboot[26] język, który przypomina język PHP,
- Pizza, pochodna języka Java ze wskaźnikami i algebraicznymi typami danych,
- Pnuts,
- Scala[27]
- Stab[28], w którym sposób programowania podobny jest do tego w języku C Sharp,
- Sleep, proceduralny, skryptowy język programowania zainspirowany językami Perl i Objective-C.
- kod języka V[29] może być kompilowany do kodu bajtowego Javy,
- X10, język stworzony przez firmę IBM,
- Yeti[30], funkcjonalny język programowania.
Przypisy
edytuj- ↑ Understanding bytecode makes you a better programmer (Rozumienie kodu bajtowego czyni cię lepszym programistą). (ang.).
- ↑ Charles Nutter: InvokeDynamic: Actually Useful?. 2007-01-03. [dostęp 2011-06-23]. (ang.).
- ↑ JSR 292 (ang.)
- ↑ Strona projektu Jawk (SourceForge)
- ↑ Strona główna projektu AMPC
- ↑ Strona Micro Focus JVM Visual COBOL. [dostęp 2011-06-23]. [zarchiwizowane z tego adresu (2011-06-01)].
- ↑ Veryant isCobol
- ↑ projekt ABCL
- ↑ Erjang Wiki
- ↑ Strona projektu myForth
- ↑ Strona projektu jLogo
- ↑ Strona projektu XLogo
- ↑ Strona projektu Kahlua
- ↑ Strona projektu Luaj (SourceForge)
- ↑ Strona projektu Jill (Google)
- ↑ Strona projektu OCaml
- ↑ Strona projektu IBM WebSphere sMash PHP. [dostęp 2011-06-23]. [zarchiwizowane z tego adresu (2018-07-22)].
- ↑ Strona projektu Caucho Quercus
- ↑ Strona projektu JTcl
- ↑ Strona projektu Alef (SourceForge)
- ↑ Strona projektu Ateji PX. [dostęp 2011-06-23]. [zarchiwizowane z tego adresu (2014-02-24)].
- ↑ Strona projektu Fantom
- ↑ Strona projektu Hecl
- ↑ Strona projektu Jaskell. [dostęp 2011-06-23]. [zarchiwizowane z tego adresu (2006-02-20)].
- ↑ Strona projektu Mirah
- ↑ Strona projektu PHP.reboot
- ↑ What is Scala? | The Scala Programming Language [online], www.scala-lang.org [dostęp 2017-06-16] [zarchiwizowane z adresu 2017-06-24] .
- ↑ Strona projektu Stab (Google)
- ↑ Strona główna języka V. [dostęp 2011-06-23]. [zarchiwizowane z tego adresu (2010-04-13)].
- ↑ Strona języka Yeti. [dostęp 2011-06-23]. [zarchiwizowane z tego adresu (2011-07-11)].
Bibliografia
edytuj- Specyfikacja JVM (ang.)
- Języki programowania przystosowane dla JVM (ang.)
- Bytecode Visualizer LT – edytor i debugger kodu bajtowego (plugin dla Eclipse) (ang.)
- Java Class Unpacker – plugin dla Total Commander, dzięki niemu można otwierać pliki dla JVM jak archiwa i zobaczyć pola i metody jako pliki. Może także pokazać kod bajtowy skrótem F3