A Java bájtkód a Java virtuális gép (JVM) által végrehajtható utasítások megjelenési formája; tehát olyan bájtsorozat, amely a JVM által végrehajtható utasításokat reprezentál. Felfogható a virtuális gép „gépi kódjaként” is, bár ez a kód nem egy adott hardveres architektúrához kötődik, hanem a hardver fölötti rétegen működő virtuális gép specifikációjához. A Java bájtkódot a JVM értelmezője hajtja végre, az emulátorokhoz hasonlóan, vagy futási időben fordul le a gazdagép hardverének gépi kódjára (JIT módszer).

Minden bájtkód egy egybájtos – egy bájton tárolt – opkód, bár néhány opkódnak paraméterei is vannak, amelyek így több-bájtos utasításokat eredményeznek. A bájtkódok nem használják ki az egy bájton rendelkezésre álló 256 lehetőséget. 51 kód fenntartott a jövőbeli felhasználásra. Ezen felül a Sun Microsystems, a Java platform eredeti kifejlesztője, három értéket véglegesen „nem megvalósítottnak” jelölt, tehát ezekhez a kódokhoz a jövőben sem lesz művelet hozzárendelve.VM Spec - Reserved Opcodes

Kapcsolat a Java nyelvvel A Java programozónak nem kell tisztában lennie vagy foglalkoznia a java bájtkóddal, mivel az automatikusan készül a program fordításakor. Egyes fejlesztői csoportok véleménye szerint a java bájtkód lényegének – pl. a Java fordítóprogram hogyan készíti el a kódot vagy a virtuális gép hogyan hajtja végre a kódot – akár csak nagy vonalakban való ismerete segítheti a programozót, ahhoz hasonlóan, ahogy az assembly ismerete segíti a C vagy C++ programozókat.Understanding bytecode makes you a better programmerA Formal Introduction to the Compilation of Java, Stephan Diehl, "Software - Practice and Experience", Vol. 28(3), pages 297-327, March 1998.

Utasítások Lásd még: Java bájtkód utasítások listája

Az opkódok a virtuális gép elemi utasításainak kódjai, ill. minden utasítást egy egybájtos opkód jelöl. Mivel egy bájt 256 lehetséges értéket vehet fel, ezért a lehetséges opkódok száma is ugyanennyi. A 256 érték közül a 0x00A számok itt hexadecimális formában állnak, ld. A hexadecimális szám felírási módjai értéktől a 0xca értékig terjedő szakaszba eső, valamint a 0xfe és a 0xff értékekhez van hozzárendelve utasítás. A 0xca egy a hibakereső programok / debuggerek számára fenntartott utasítás, maga a nyelv nem használja. Hasonlóan, a 0xfe és 0xff kódokat sem használja a nyelv, ezek a virtuális gép belső használatára vannak fenntartva.

Az utasítások nagy vonalakban a következő csoportokba sorolhatók:

Betöltés és tárolás (pl. aload_0, istore) Számolási (aritmetikai) és logikai utasítások (pl. ladd, fcmpl) Típuskonverzió (pl. i2b, d2i) Objektumok létrehozása és objektumműveletek (new, putfield) Operandusverem kezelése (pl. swap, dup2) Programvezérlési utasítások (pl. ifeq, goto) Metódushívási és visszatérési utasítások (pl. invokespecial, areturn)

Ezeken felül van néhány utasítás olyan specializáltabb feladatok céljaira is, mint pl. a kivételek kiváltása, szinkronizáció, egyebek.

A legtöbb utasításnak van valamilyen előtagja (prefixe) és utótagokat (szuffixumok) is kaphat, amelyek az utasítás által kezelt operandusok típusára vonatkoznak. Ezek a következők:

Prefix/Suffix Operandus típus i integer l long s short b byte c character f float d double z boolean a reference

Például az „iadd” két integer érték, míg a „dadd” két duplapontos érték összeadását jelöli. A „const”, „load”, és „store” utasítások „_n” alakú utótagokat kaphatnak, ahol az n egy 0 és 3 közötti szám lehet a „load” és „store” utasításoknál. A „const” után az n maximuma változik a típustól függően. A „const” utasítások a megadott típusú értékeket a verembe teszik (a verem tetejére helyezik, push művelet). Például az „iconst_5” egy integer 5 értéket tesz a verembe míg a „dconst_1” egy duplapontos 1 értéket. Van egy „aconst_null” utasítás is, amely a „null” értéket teszi a verembe (ezt az értéket a Java nyelvben általánosan használják). A „load” és a „store” utasításokban az n értéke a változó helyfoglalására vonatkozik a változólistában. Az „aload_0” utasítás a 0. változóban tárolt objektumot helyezi a verem tetejére (ami általában a „this” objektum). Az „istore_1” a verem tetején lévő integer értéket az 1. változóba írja. A nagyobb számú / indexű változók esetén az utótag elmarad és az utasításban operátorokkal jelölik azokat.

Számítási modell

A Java bájtkód számítási modellje megegyezik a veremalapú programozási nyelvek számítási modelljével. Például lássuk egy x86-os processzor assembly nyelvű kódrészletét:

mov eax, byte [ebp-4] mov edx, byte [ebp-8] add eax, edx mov ecx, eax

Ez a kód két értéket ad össze és az eredményt egy harmadik helyre (itt: regiszterbe) írja. Az ugyanezt végrehajtó visszafejtett bájtkód a következő lehet:

0 iload_1 1 iload_2 2 iadd 3 istore_3

Ebben az esetben a két összeadandó érték a verembe kerül, ahonnan az összeadó utasítás előveszi azokat, összeadja az értékeket, és az eredményt a verembe teszi. A tároló utasítás a verem tetején lévő értéket kiveszi és a változóba (a változótáblázatban megjelölt területre) írja. Az utasítások előtti számok csak az utasítások indexét (ofszetjét) mutatják az adott metódus kezdetétől számítva. A veremorientált modell kiterjed a nyelv objektumorientált szempontjaira is. Például egy "getName()" nevű metódus hívása a következőképpen nézhet ki:

Method java.lang.String getName() 0 aload_0 // A "this" objektum a változótáblázat 0. helyén van tárolva 1 getfield #5 <Field java.lang.String name> // Ez az utasítás levesz (pop) egy objektumot a stack tetejéről, előveszi abból // a megadott mező értékét, majd a mező értéket a verembe rakja. // Ebben a példában a "name" mező megfelel az ötödik konstansnak // a class állandó-területén (constant pool). 4 areturn // Visszaadja a verem tetején álló objektumot a metódusból.

Példa

Tekintsük az alábbi Java kódot: 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);

A Java fordító a következő Java bájtkódot állíthatja elő a fordítás során, feltételezve, hogy a fenti kódrészlet egy metódus része: 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

Előállítás

A legismertebb nyelv, amely bájtkódot produkál a JVM számára, a Java. Eredetileg csak egy fordító létezett, a Sun Microsystems javac fordítóprogramja, amely a Java nyelvű forráskódot Java bájtkódra fordítja. de mivel a Java bájtkódra vonatkozó specifikációk mára nyilvánosak és rendelkezésre állnak, más szereplők is készítettek Java bájtkódot előállító fordítóprogramokat. Néhány példa:

Jikes, Java forráskódból Java bájtkódot készít (IBM fejlesztés, C++ nyelven készült, Java 5-ig kompatibilis, részben) Espresso, Java forráskódból Java bájtkódot készít (csak Java 1.0) GCJ, „GNU Compiler for Java”, Java forráskódból Java bájtkódot készít; képes natív gépi kódot is készíteni, a GNU Compiler Collection (GCC) része.

Néhány projektben Java assembler is található, amely lehetővé teszi a Java bájtkód kézi elkészítését. Az assemly kód géppel is generálható, például a fordítóprogram célplatform megjelölésével. Néhány Java assembler:

Jasmin, Java osztályok leírhatók egyszerű assembly-szerű szintaxissal és JVM utasításkészlettel, Java class fájlt készít Jamaica, egy macro assembly nyelv a Java virtuális géphez. Java szintaxis használható az osztály interfész leírásában. A metódusok törzse Java bájtkód utasításokkal írható.

További fordítóprogramok is készültek, amelyek különböző programnyelvekről képesek Java bájtkód előállítására, a fordítóprogram célplatformjaként a Java virtuális gép megjelölésével:

ColdFusion JRuby és Jython, Ruby- és Python-alapú szkriptnyelvek Groovy, Java nyelven alapuló szkriptnyelv Scala, egy típusbiztos általános célú programozási nyelv, amely támogatja az objektumorientált és funkcionális programozást JGNAT és AppletMagic, Ada nyelvű forráskódból fordít Java bájtkódra C-ről Java bájtkódra fordító fordítóprogramok Clojure MIDletPascal JavaFX Script kód szintén lefordítható Java bájtkódra

Végrehajtás A Java bájtkódot a Java virtuális gép általi végrehajtásra tervezték. Mostanára több Java virtuális gép is elkészült, különböző platformokra, egyesek nyíltak, mások kereskedelmi célú termékek.

Ha valamilyen okból a Java bájtkód végrehajtása a Java virtuális géppel nemkívánatos, akkor a fejlesztőnek lehetősége van a Java forrásprogramot vagy a Java bájtkódot natív gépi kódra fordítani; ezt megteheti ingyenes eszközökkel is, pl. GCJ.

Néhány processzor képes a Java bájtkód natív végrehajtására; ezeket a processzorokat nevezik Java processzoroknak.

Dinamikus nyelvek támogatása

A Java virtuális gép nyújt némi támogatást a dinamikus típusú nyelvekhez. A JVM utasítások többsége statikus típusú – abban az értelemben, hogy a metódushívások paramétereinek (signature) típusellenőrzése fordítási időben történik, és nincs olyan mechanizmus, amely elhalasztaná / kitolná ezt a döntést a futási időbe, vagy valamilyen alternatív módszerrel kezelné a metódusok indítását.

A JSR 292 (Supporting Dynamically Typed Languages on the Java™ Platform, Dinamikus típusú nyelvek támogatása a Java™ Platformon)see JSR 292 specifikációs javaslat bevezet egy új invokedynamic utasítást a JVM szintjén, amely lehetővé teszi a dinamikus típusellenőrzésen alapuló metódushívást (amely a már létező, statikus típusellenőrzésű invokevirtual utasítás helyett lenne használható). A Da Vinci Machine egy virtuális gép prototípus-szintű megvalósítása, amely a dinamikus nyelvek támogatását célzó JVM kiterjesztéseket gyűjti egybe. A J2SE 7-es változatát támogató virtuális gépek szintén tartalmazzák az invokedynamic opkódot.

Kapcsolódó szócikkek Java bájtkód utasítások listája Java class file JVM nyelvek listája Java virtuális gépek listája Java visszaportoló eszközök C-ről JVM-re fordító programok JStik Common Intermediate Language (CIL)

Jegyzetek

Fordítás

Források

További információk

Sun's Java Virtual Machine Specification Programming Languages for the Java Virtual Machine Bytecode Visualizer – bájtkód nézegető és debugger (ingyenes Eclipse plugin) AdaptJ StackTrace – bájtkód szintű debugger eszköz, verem, változók és végrehajtás vezérléssel Java Class Unpacker – Total Commander plugin, class fájlok megnyitása, nézegető; metódusok, mezők és bájtkód megjelenítés

Kategória:Java Kategória:Java virtuális gépek Kategória:Programozási nyelvek