Java bytecode - Java bytecode

Java bytecode er instruktionssæt for den virtuelle Java -maskine (JVM).

Forhold til Java

En Java -programmør behøver slet ikke at være opmærksom på eller forstå Java -bytecode. Men som foreslået i IBM developerWorks -journal, "At forstå bytecode og hvilken bytecode der sandsynligvis vil blive genereret af en Java -compiler, hjælper Java -programmereren på samme måde som viden om samling hjælper C- eller C ++ -programmereren."

Instruktion sæt arkitektur

JVM er både en stakmaskine og en registermaskine . Hver ramme til et metodeopkald har en "operandstabel" og en række "lokale variabler". Operandstakken bruges til operander til beregninger og til modtagelse af returværdien af ​​en kaldet metode, mens lokale variabler tjener det samme formål som registre og også bruges til at sende metodeargumenter. Den maksimale størrelse af operandstakken og det lokale variable array, beregnet af kompilatoren, er en del af attributterne for hver metode. Hver kan være uafhængigt dimensioneret fra 0 til 65535 værdier, hvor hver værdi er 32 bit. longog doubletyper, som er 64 bit, optager to på hinanden følgende lokale variabler (som ikke behøver at være 64-bit justeret i det lokale variabels array) eller en værdi i operandstakken (men tælles som to enheder i dybden af ​​stakken) .

Instruktionssæt

Hver bytekode er sammensat af en byte, der repræsenterer opcode , sammen med nul eller flere bytes for operander.

Af de 256 mulige byte-lange opcoder fra 2015 er 202 i brug (~ 79%), 51 er reserveret til fremtidig brug (~ 20%), og 3 instruktioner (~ 1%) er permanent forbeholdt JVM-implementeringer til brug. To af disse ( impdep1og impdep2) skal levere fælder til henholdsvis implementeringsspecifik software og hardware. Den tredje bruges til debuggere til at implementere breakpoints.

Instruktioner falder i en række brede grupper:

  • Ilæg og gem (f.eks aload_0. istore)
  • Aritmetik og logik (f.eks ladd. fcmpl)
  • Type konvertering (f.eks i2b. d2i)
  • Oprettelse og manipulation af objekter ( new, putfield)
  • Operand stack management (f.eks swap. dup2)
  • Kontroloverførsel (f.eks ifeq. goto)
  • Metodeopkald og returnering (f.eks invokespecial. areturn)

Der er også et par instruktioner til en række mere specialiserede opgaver som undtagelseskast, synkronisering osv.

Mange instruktioner har præfikser og/eller suffikser, der refererer til de typer operander, de opererer på. Disse er som følger:

Præfiks/suffiks Operand type
i heltal
l lang
s kort
b byte
c Karakter
f flyde
d dobbelt
a reference

For eksempel iaddvil tilføje to heltal, mens daddvil tilføje to doubles. Den const, loadog storeinstruktionerne kan også have et suffiks af formularen , hvor n er et tal fra 0–3 for og . Maksimum n for er forskellig efter type. _nloadstoreconst

De constinstruktioner skubbe en værdi af den angivne type på stakken. For eksempel iconst_5skubber et helt tal (32 bit værdi) med værdien 5 på stakken, mens dconst_1det skubber en dobbelt (64 bit floating point værdi) med værdien 1 på stakken. Der er også en aconst_null, som skubber en nullreference. Den n for loadog storeinstruktioner angiver indeks i lokal variabel array til belastningen fra eller butik til. Den aload_0instruktion skubber objektet i lokal variabel 0 på stablen (dette er normalt thisobjekt). istore_1gemmer heltalet på toppen af ​​stakken i lokal variabel 1. For lokale variabler ud over 3 er suffikset droppet, og operander skal bruges.

Eksempel

Overvej følgende Java -kode:

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);
}

En Java -kompilator kan oversætte Java -koden ovenfor til bytecode som følger, forudsat at ovenstående blev sat i en metode:

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

Generation

Det mest almindelige sprog, der er målrettet mod Java -virtuel maskine ved at producere Java -bytecode, er Java. Oprindeligt eksisterede kun én compiler, den javac compileren fra Sun Microsystems , der samler Java-kildekode til Java bytecode; men fordi alle specifikationerne for Java bytecode nu er tilgængelige, har andre parter leveret compilers, der producerer Java bytecode. Eksempler på andre kompilatorer omfatter:

  • Eclipse compiler til Java (ECJ)
  • Jikes , kompilerer fra Java til Java bytecode (udviklet af IBM , implementeret i C ++ )
  • Espresso, kompilerer fra Java til Java bytecode (kun Java 1.0)
  • GNU Compiler til Java (GCJ), kompilerer fra Java til Java bytecode; den kan også kompilere til native maskinkode og var en del af GNU Compiler Collection (GCC) indtil version 6.

Nogle projekter giver Java -montører mulighed for at skrive Java -bytecode i hånden. Samlingskode kan også genereres af en maskine, f.eks. Af en kompiler, der er målrettet mod en virtuel Java -maskine . Bemærkelsesværdige Java -montører omfatter:

  • Jasmin , tager tekstbeskrivelser for Java-klasser, skrevet i en simpel montagelignende syntaks ved hjælp af Java virtual machine instruktionssæt og genererer en Java-klassefil
  • Jamaica, en makro assembler for Java virtuel maskine . Java -syntaks bruges til klasse- eller grænseflade -definition. Metodelegemer specificeres ved hjælp af bytecode -instruktioner.
  • Krakatau Bytecode Tools, indeholder i øjeblikket tre værktøjer: en decompiler og demonterer for Java -klassefiler og en assembler til at oprette klassefiler.
  • Lilac, en assembler og adskiller til den virtuelle Java -maskine .

Andre har udviklet kompilatorer til forskellige programmeringssprog til at målrette mod den virtuelle Java -maskine, såsom:

Udførelse

Der findes flere virtuelle Java -maskiner i dag til at udføre Java -bytecode, både gratis og kommercielle produkter. Hvis udførelse af bytecode i en virtuel maskine er uønsket, kan en udvikler også kompilere Java -kildekode eller bytecode direkte til native maskinkode med værktøjer såsom GNU Compiler for Java (GCJ). Nogle processorer kan eksekvere Java bytecode indbygget. Sådanne processorer betegnes Java -processorer .

Understøttelse af dynamiske sprog

Den virtuelle Java -maskine giver en vis støtte til dynamisk indtastede sprog . Det meste af det eksisterende JVM -instruktionssæt er statisk skrevet - i den forstand, at metodeopkald har deres signaturer typekontrolleret på kompileringstidspunktet , uden en mekanisme til at udsætte denne beslutning om at køre tid eller til at vælge metodeforsendelse ved en alternativ tilgang.

JSR 292 ( understøtter dynamisk indtastede sprog på Java-platformen ) tilføjede en ny invokedynamicinstruktion på JVM-niveau for at tillade fremkaldelse af metoder afhængig af dynamisk typekontrol (i stedet for den eksisterende statisk typekontrolleredeinvokevirtual instruktion). Den Da Vinci Machine er en prototype virtuel maskine implementering, at værter JVM udvidelser til formål at støtte dynamiske sprog. Alle JVM'er, der understøtter JSE 7, inkluderer også invokedynamicopcode.

Se også

Referencer

eksterne links