Wandle einen Integer-Wert in einen Byte-Wert um.
Die Bits 7-0 des aus 4 Bytes bestehenden Integer-Wertes value
werden beachtet, um einen Byte-Wert zu erhalten. Der Maximalwert eines Beispiel 1: int a = 320; 0: sipush 320 3: istore_1 byte b = (byte)a; 4: iload_1 5: i2b 6: istore_2 Binäre Darstellung: 320i = (00000000 00000000 00000001 01000000)b 64b = (00000000 00000000 00000000 01000000)b Die Variable Beispiel 2: int a = 384; 0: sipush 384 3: istore_1 byte b = (byte)a; 4: iload_1 5: i2b 6: istore_2 Binäre Darstellung: 384i = (00000000 00000000 00000001 10000000)b -128b = (11111111 11111111 11111111 10000000)b Die Variable
Wandle einen Integer-Wert in einen Char-Wert um.
Das Ergebnis der Umwandlung result ist wieder vom Typ
Beispiel: int a = 65; 0: bipush 65
2: istore_1
char b = (char)a; 3: iload_1
4: i2c
5: istore_2
int c = b; 6: iload_2
7: istore_3 Der Char-Wert wird durch die virtuelle Java-Maschine als public class Test { public static void main(String[] args) { int a = 65; char b = (char)a; int c = b; System.out.println("a = " + a); System.out.println("b = " + b); System.out.println("c = " + c); } } Konsolenausgabe: a = 65 b = A c = 65
Wandle einen
Beispiel: int a = 3; 0: iconst_3 1: istore_1 double b = a; 2: iload_1 3: i2d 4: dstore_2 Binäre Darstellung: 3i = (00000000 00000000 00000000 00000011)b 3.0d = (01000000 00001000 00000000 00000000 00000000 00000000 00000000 00000000)b Die Variable
Wandle einen
Beispiel: int a = 3; 0: iconst_3 1: istore_1 float b = a; 2: iload_1 3: i2f 4: fstore_2 Binäre Darstellung: 3i = (00000000 00000000 00000000 00000011)b 3.0f = (01000000 01000000 00000000 00000000)b Die Variable
Wandle einen
Beispiel: int a = 3; 0: iconst_3 1: istore_1 long b = a; 2: iload_1 3: i2l 4: lstore_2 Binäre Darstellung: 3i = (00000000 00000000 00000000 00000011)b 3l = (00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000011)b
Wandle einen Integer-Wert in einen Short-Wert um.
Die Bits 15-0 des aus 4 Bytes bestehenden Integer-Wertes value
werden beachtet, um einen Short-Wert zu erhalten. Der Maximalwert eines Beispiel 1: int a = 81920; 0: ldc #2; //int 81920 2: istore_1 short b = (short)a; 3: iload_1 4: i2s 5: istore_2 Binäre Darstellung: 81920i = (00000000 00000001 01000000 00000000)b 16384s = (00000000 00000000 01000000 00000000)b Die Variable Beispiel 2: int a = 98304; 0: ldc #2; //int 98304 2: istore_1 short b = (short)a; 3: iload_1 4: i2s 5: istore_2 Binäre Darstellung: 98304i = (00000000 00000001 10000000 00000000)b -32768s = (11111111 11111111 10000000 00000000)b Die Variable
Addiere zwei
Die beiden obersten Elemente werden vom Stapel genommen und addiert: result = value1 + value2. Beispiel: int a = 3; 0: iconst_3
1: istore_1
int b = 4; 2: iconst_4
3: istore_2
int c = a + b; 4: iload_1
5: iload_2
6: iadd
7: istore_3
Lade einen
Mit Hilfe von arrayref und index
wird ein Beispiel: int[] i = {4, 5}; 0: iconst_2
1: newarray int
3: dup
4: iconst_0
5: iconst_4
6: iastore
7: dup
8: iconst_1
9: iconst_5
10: iastore
11: astore_1
int i0 = i[0]; 12: aload_1
13: iconst_0
14: iaload
15: istore_2 Mit
Verknüpfe zwei
Es gilt: result = value1 & value2 Beispiel: 32762 & 31 = 26 int a = 32762; 0: sipush 32762 3: istore_1 int b = 31; 4: bipush 31 6: istore_2 int c = a & b; 7: iload_1 8: iload_2 9: iand 10: istore_3 Binäre Darstellung: 32762 = (00000000 00000000 01111111 11111010)b 31 = (00000000 00000000 00000000 00011111)b 26 = (00000000 00000000 00000000 00011010)b
Speichere einen
Auf dem Operandenstapel befinden sich, vor der Ausführung des Befehls, die
Referenz auf das Array, der Index des Elements im Array und der zu speichernde
Lege die Beispiel: Siehe dazu
Lege die Beispiel: int i = 0; 0: iconst_0
1: istore_1
Lege die Beispiel: Siehe dazu
Lege die Beispiel: Siehe dazu
Lege die Beispiel: Siehe dazu
Lege die Beispiel: Siehe dazu
Lege die Beispiel: Siehe dazu
Dividiere zwei
Die beiden obersten Elemente werden vom Stapel genommen und die folgende Division wird durchgeführt: result = value1 / value2. Da das Ergebnis wiederum eine Ganzzahl sein muss, werden mögliche Nachkommastellen nicht beachtet. Beispiel: int a = 9; 0: bipush 9
2: istore_1
int b = 4; 3: iconst_4
4: istore_2
int c = a / b; 5: iload_1
6: iload_2
7: idiv
8: istore_3 Der Inhalt der Variablen
Führe einen Vergleich zweier Referenzen durch. Verzweige, falls gilt: value1 = value2.
Falls die Bedingung erfüllt ist, wird an die Stelle im Programm verzweigt, die sich aus einem Offset ergibt. Der vorzeichenbehaftete Offset berechnet sich zu: (branchbyte1 << 8) | branchbyte2. Beispiel: String a = "x"; 0: ldc #2; //String x
2: astore_1
String b = "x"; 3: ldc #2; //String x
5: astore_2
boolean c = (a != b); 6: aload_1
7: aload_2
8: if_acmpeq 15
11: iconst_1
12: goto 16
15: iconst_0
16: istore_3 Da die Inhalte (Referenzen) der beiden Variablen
Führe einen Vergleich zweier Referenzen durch. Verzweige, falls gilt: value1 ≠ value2 (ungleich).
Falls die Bedingung erfüllt ist, wird an die Stelle im Programm verzweigt, die sich aus einem Offset ergibt. Der vorzeichenbehaftete Offset berechnet sich zu: (branchbyte1 << 8) | branchbyte2. Beispiel: String a = "x"; 0: ldc #2; //String x
2: astore_1
String b = "x"; 3: ldc #2; //String x
5: astore_2
boolean c = (a == b); 6: aload_1
7: aload_2
8: if_acmpne 15
11: iconst_1
12: goto 16
15: iconst_0
16: istore_3 Da die Inhalte (Referenzen) der beiden Variablen
Führe einen Vergleich zweier
Falls die Bedingung erfüllt ist, wird an die Stelle im Programm verzweigt, die sich aus einem Offset ergibt. Der vorzeichenbehaftete Offset berechnet sich zu: (branchbyte1 << 8) | branchbyte2. Beispiel: int a = 3; 0: iconst_3
1: istore_1
int b = 4; 2: iconst_4
3: istore_2
boolean c = (a != b); 4: iload_1
5: iload_2
6: if_icmpeq 13
9: iconst_1
10: goto 14
13: iconst_0
14: istore_3 Da die Inhalte der beiden Variablen
Führe einen Vergleich zweier
Falls die Bedingung erfüllt ist, wird an die Stelle im Programm verzweigt, die sich aus einem Offset ergibt. Der vorzeichenbehaftete Offset berechnet sich zu: (branchbyte1 << 8) | branchbyte2. Beispiel: int a = 3; 0: iconst_3
1: istore_1
int b = 4; 2: iconst_4
3: istore_2
boolean c = (a < b); 4: iload_1
5: iload_2
6: if_icmpge 13
9: iconst_1
10: goto 14
13: iconst_0
14: istore_3 Da der Inhalt der Variablen
Führe einen Vergleich zweier
Falls die Bedingung erfüllt ist, wird an die Stelle im Programm verzweigt, die sich aus einem Offset ergibt. Der vorzeichenbehaftete Offset berechnet sich zu: (branchbyte1 << 8) | branchbyte2. Beispiel: int a = 3; 0: iconst_3
1: istore_1
int b = 4; 2: iconst_4
3: istore_2
boolean c = (a <= b); 4: iload_1
5: iload_2
6: if_icmpgt 13
9: iconst_1
10: goto 14
13: iconst_0
14: istore_3 Da der Inhalt der Variablen
Führe einen Vergleich zweier
Falls die Bedingung erfüllt ist, wird an die Stelle im Programm verzweigt, die sich aus einem Offset ergibt. Der vorzeichenbehaftete Offset berechnet sich zu: (branchbyte1 << 8) | branchbyte2. Beispiel: int a = 3; 0: iconst_3
1: istore_1
int b = 4; 2: iconst_4
3: istore_2
boolean c = (a > b); 4: iload_1
5: iload_2
6: if_icmple 13
9: iconst_1
10: goto 14
13: iconst_0
14: istore_3 Da der Inhalt der Variablen
Führe einen Vergleich zweier
Falls die Bedingung erfüllt ist, wird an die Stelle im Programm verzweigt, die sich aus einem Offset ergibt. Der vorzeichenbehaftete Offset berechnet sich zu: (branchbyte1 << 8) | branchbyte2. Beispiel: int a = 3; 0: iconst_3
1: istore_1
int b = 4; 2: iconst_4
3: istore_2
boolean c = (a >= b); 4: iload_1
5: iload_2
6: if_icmplt 13
9: iconst_1
10: goto 14
13: iconst_0
14: istore_3 Da der Inhalt der Variablen
Führe einen Vergleich zweier
Falls die Bedingung erfüllt ist, wird an die Stelle im Programm verzweigt, die sich aus einem Offset ergibt. Der vorzeichenbehaftete Offset berechnet sich zu: (branchbyte1 << 8) | branchbyte2. Beispiel: int a = 3; 0: iconst_3
1: istore_1
int b = 4; 2: iconst_4
3: istore_2
boolean c = (a == b); 4: iload_1
5: iload_2
6: if_icmpne 13
9: iconst_1
10: goto 14
13: iconst_0
14: istore_3 Da der Inhalt der Variablen
Führe eine Vergleich eines
Aus den vorzeichenlosen Verzweigungsbytes wird ein vorzeichenbehafteter Offset
berechnet: (branchbyte1 << 8) | branchbyte2.
Der aktuelle Programmzähler (PC) zeigt auf die Verzweigungsanweisung Beispiel: int a = 3; 0: iconst_3
1: istore_1
boolean c = (a != 0); 2: iload_1
3: ifeq 10
6: iconst_1
7: goto 11
10: iconst_0
11: istore_2 Da der Inhalt der Variablen
Führe eine Vergleich eines
Aus den vorzeichenlosen Verzweigungsbytes wird ein vorzeichenbehafteter Offset
berechnet: (branchbyte1 << 8) | branchbyte2.
Der aktuelle Programmzähler (PC) zeigt auf die Verzweigungsanweisung Beispiel: int a = 3; 0: iconst_3
1: istore_1
boolean c = (a < 0); 2: iload_1
3: ifge 10
6: iconst_1
7: goto 11
10: iconst_0
11: istore_2 Da der Inhalt der Variablen
Führe eine Vergleich eines
Aus den vorzeichenlosen Verzweigungsbytes wird ein vorzeichenbehafteter Offset
berechnet: (branchbyte1 << 8) | branchbyte2.
Der aktuelle Programmzähler (PC) zeigt auf die Verzweigungsanweisung Beispiel: int a = 3; 0: iconst_3
1: istore_1
boolean c = (a <= 0); 2: iload_1
3: ifgt 10
6: iconst_1
7: goto 11
10: iconst_0
11: istore_2 Da der Inhalt der Variablen
Führe eine Vergleich eines
Aus den vorzeichenlosen Verzweigungsbytes wird ein vorzeichenbehafteter Offset
berechnet: (branchbyte1 << 8) | branchbyte2.
Der aktuelle Programmzähler (PC) zeigt auf die Verzweigungsanweisung Beispiel: int a = 3; 0: iconst_3
1: istore_1
boolean c = (a > 0); 2: iload_1
3: ifle 10
6: iconst_1
7: goto 11
10: iconst_0
11: istore_2 Da der Inhalt der Variablen
Führe eine Vergleich eines
Aus den vorzeichenlosen Verzweigungsbytes wird ein vorzeichenbehafteter Offset
berechnet: (branchbyte1 << 8) | branchbyte2.
Der aktuelle Programmzähler (PC) zeigt auf die Verzweigungsanweisung Beispiel: int a = 3; 0: iconst_3
1: istore_1
boolean c = (a >= 0); 2: iload_1
3: iflt 10
6: iconst_1
7: goto 11
10: iconst_0
11: istore_2 Da der Inhalt der Variablen
Führe eine Vergleich eines
Aus den vorzeichenlosen Verzweigungsbytes wird ein vorzeichenbehafteter Offset
berechnet: (branchbyte1 << 8) | branchbyte2.
Der aktuelle Programmzähler (PC) zeigt auf die Verzweigungsanweisung Beispiel: int a = 3; 0: iconst_3
1: istore_1
boolean c = (a == 0); 2: iload_1
3: ifne 10
6: iconst_1
7: goto 11
10: iconst_0
11: istore_2 Da der Inhalt der Variablen
Verzweige, falls der Wert einer Referenz (Verweis auf ein Objekt) nicht die
vordefinierte Konstante
Für eine mögliche Verzweigung wird aus den beiden Verzweigungsbytes ein
vorzeichenbehafteter 16-Bit-Offset wie folgt berechnet:
(branchbyte1 << 8) | branchbyte2.
Falls value nicht den Wert Beispiel: Object obj = null; 0: aconst_null
1: astore_1
if (obj == null) { 2: aload_1
3: ifnonnull 14
obj = new Object(); 6: new #2; //class java/lang/Object
9: dup
10: invokespecial #1;
//Method java/lang/Object."<init>":()V
} 13: astore_1
14: return; //z.B. aus main-Methode
Verzweige, falls der Wert einer Referenz (Verweis auf ein Objekt) die
vordefinierte Konstante
Für eine mögliche Verzweigung wird aus den beiden Verzweigungsbytes ein
vorzeichenbehafteter 16-Bit-Offset wie folgt berechnet:
(branchbyte1 << 8) | branchbyte2.
Falls value den Wert Beispiel: Object obj = new Object(); 0: new #2; //class java/lang/Object
3: dup
4: invokespecial #1;
//Method java/lang/Object."<init>":()V
7: astore_1
if (obj != null) { 8: aload_1
9: ifnull 14
obj = null; 12: aconst_null
} 13: astore_1
14: return; //z.B. aus main-Methode
Erhöhe bzw. verringere einen
Bei index im Array der lokalen Variablen befindet sich
ein Wert vom Typ Beispiel 1: Postinkrement int a = 3; 0: iconst_3
1: istore_1
int b = a++; 2: iload_1
3: iinc 1, 1
6: istore_2
Ergebnis: a = 4, b = 3 Beispiel 2: Prädekrement int a = 3; 0: iconst_3
1: istore_1
int b = --a; 2: iinc 1, -1
5: iload_1
6: istore_2
Ergebnis: a = 2, b = 2 Beispiel 3:
Additionszuweisungen int a = 3; 0: iconst_3 1: istore_1 a += 127; 2: iinc 1, 127 a += 128; 5: iinc_w 1, 128 Ergebnis: a = 258 Die drei Quellcode-Anweisungen des Beispiels werden in die hexadezimale
Zahlenabfolge
Lade einen
Der Eintrag value im Array bei diesem Index muss vom
Typ Beispiel: public class Test {
public static void main(String[] args) {
int i1 = args.length; 0: aload_0
1: arraylength
2: istore_1
int i2 = 0; 3: iconst_0
4: istore_2
int i3 = 1; 5: iconst_1
6: istore_3
int i4 = 2; 7: iconst_2
8: istore 4
int i5 = i1 + i2 + i3 + i4; 10: iload_1
11: iload_2
12: iadd
13: iload_3
14: iadd
15: iload 4
17: iadd
18: istore 5
}
} Das Laden der Zahlenwerte aus dem Array der lokalen Variablen übernehmen
zunächst die mit einem Byte codierten JVM-Befehle
Lade den
Der Eintrag im Array bei Index 0 muss vom Typ
Lade den
Der Eintrag im Array bei Index 1 muss vom Typ
Lade den
Der Eintrag im Array bei Index 2 muss vom Typ
Lade den
Der Eintrag im Array bei Index 3 muss vom Typ
Multipliziere zwei
Die beiden obersten Elemente werden vom Stapel genommen und miteinander multipliziert: result = value1 * value2. Beispiel: int a = 3; 0: iconst_3
1: istore_1
int b = 4; 2: iconst_4
3: istore_2
int c = a * b; 4: iload_1
5: iload_2
6: imul
7: istore_3
Negiere einen
Es gilt: result = -value. Die
Negation eines Beispiel: int a = 3; 0: iconst_3 1: istore_1 int b = -a; 2: iload_1 3: ineg 4: istore_2 int c = 0 - a; 5: iconst_0 6: iload_1 7: isub 8: istore_3
Stelle fest, ob eine Instanz (Objekt) von einem bestimmten Typ ist bzw. zu einem bestimmten Typ (z.B. Klasse) gehört.
Mit Hilfe der vorzeichenlosen Bytes indexbyte1 und
indexbyte2 wird ein Index im (Laufzeit-)Konstantenpool der
aktuellen Klasse berechnet: (indexbyte1 << 8) |
indexbyte2. Mit diesem Index kann eine entsprechende Referenz
auf eine Klasse, ein Array oder ein Interface erhalten werden. Der JVM-Befehl
Beispiel 1: Dem JVM-Befehl public class Test { public static void main(String[] args) { Integer i = new Integer(3); boolean b1 = i instanceof Integer; boolean b2 = i instanceof Comparable; boolean b3 = i instanceof Number; Integer[] ia = new Integer[3]; boolean b4 = ia instanceof Integer[]; System.out.println(b1); System.out.println(b2); System.out.println(b3); System.out.println(b4); } } Konsolenausgabe: true true true true Die Werte der Variablen Beispiel 2: Der Integer i = new Integer(3); 0: new #2; //class java/lang/Integer
3: dup
4: iconst_3
5: invokespecial #3; //Method
java/lang/Integer."<init>":(I)V
8: astore_1
boolean b1 = i instanceof Integer; 9: aload_1
10: instanceof #2;
//class java/lang/Integer
13: istore_2
Rufe eine Interfacemethode auf (Methode, die in einem Interface deklariert ist).
Mit Hilfe der vorzeichenlosen Bytes indexbyte1 und indexbyte2 wird ein Index im (Laufzeit-)Konstantenpool der aktuellen Klasse berechnet: (indexbyte1 << 8) | indexbyte2. Bei diesem Index befindet sich eine Konstante vom Typ Interface-Methodenreferenz. Mit Hilfe der Konstanten werden die folgenden Informationen zugänglich: Interface, in der die Methode deklariert ist, Name der Methode, Methodendeskriptor (Anzahl und Typ der Methodenparamter, Typ des Rückgabewertes). Auf dem Operandenstapel befinden sich die Referenz auf ein Objekt
objectref und die Argumente, die an die aufzurufende Methode
übergeben werden sollen. Dabei implementiert die Klasse des Objekts das Interface,
indem die aufzurufende Interfacemethode deklariert ist. Die Argumente müssen den
Vorgaben im Methodendeskriptor genügen. Bei der Ausführung des (nicht nativen)
Methodenaufrufs werden zunächst die vorhandenen Argumente
arg1, ..., argn und die Objektreferenz
vom Operandenstapel geholt und es wird ein neuer Frame für die aufzurufende Methode
erzeugt. Der Frame wird anschließend auf dem JVM-Stack abgelegt. Der erzeugte Frame
enthält einen Operandenstapel und ein Array für die lokalen Variablen der aufgerufenen
Methode. In dieses Array wird die Objektreferenz und die übergebenen Argumente
geschrieben (falls vorhanden). Der Eintrag im Array bei Index 0 enthält die Referenz
auf das Objekt objectref und bei Index 1 ist z.B. der Wert des
Arguments arg1 abgelegt. Nachdem die Objektreferenz (Stichwort:
Beispiel: Der Aufruf einer Interfacemethode wird durch die folgende Gegenüberstellung von Java-Quelltext und den zugehörigen JVM-Befehlen auf Bytecodeebene deutlich: public class Test {
public static void public static void
main(String[] args) { main(java.lang.String[]);
Code:
Integer i1 = new Integer("3"); 0: new #2; //class java/lang/Integer
3: dup
4: ldc #3; //String 3
6: invokespecial #4;
//Method java/lang/Integer."<init>"
:(Ljava/lang/String;)V
9: astore_1
Integer i2 = new Integer("4"); 10: new #2; //class java/lang/Integer
13: dup
14: ldc #5; //String 4
16: invokespecial #4;
//Method java/lang/Integer."<init>"
:(Ljava/lang/String;)V
19: astore_2
Comparable<Integer> c = i1; 20: aload_1
21: astore_3
int a = c.compareTo(i2); 22: aload_3
23: aload_2
24: invokeinterface #6, 2;
//InterfaceMethod
java/lang/Comparable.compareTo
:(Ljava/lang/Object;)I
29: istore 4
31: return
} Die beiden Zeilen Comparable<Integer> c = i1; int a = c.compareTo(i2); im Quelltext bewirken, dass der Aufruf der Interfacemethode Es sind 29 Konstanten im Konstantenpool enthalten. 1. Konstante: Methode von Klasse #8, Name/Typ #17 2. Konstante: Klasse #18 3. Konstante: String #19 4. Konstante: Methode von Klasse #2, Name/Typ #20 5. Konstante: String #21 6. Konstante: Interface-Methode von Klasse #22, Name/Typ #23 7. Konstante: Klasse #24 8. Konstante: Klasse #25 9. Konstante: Utf8 <init> 10. Konstante: Utf8 ()V 11. Konstante: Utf8 Code 12. Konstante: Utf8 LineNumberTable 13. Konstante: Utf8 main 14. Konstante: Utf8 ([Ljava/lang/String;)V 15. Konstante: Utf8 SourceFile 16. Konstante: Utf8 Test.java 17. Konstante: Name #9, Typ #10 18. Konstante: Utf8 java/lang/Integer 19. Konstante: Utf8 3 20. Konstante: Name #9, Typ #26 21. Konstante: Utf8 4 22. Konstante: Klasse #27 23. Konstante: Name #28, Typ #29 24. Konstante: Utf8 Test 25. Konstante: Utf8 java/lang/Object 26. Konstante: Utf8 (Ljava/lang/String;)V 27. Konstante: Utf8 java/lang/Comparable 28. Konstante: Utf8 compareTo 29. Konstante: Utf8 (Ljava/lang/Object;)I
Rufe eine Methode (u.a. Konstruktor) auf. Die Vorgehensweise von Methodenaufrufen durch
Mit Hilfe der vorzeichenlosen Bytes indexbyte1 und indexbyte2 wird ein Index im (Laufzeit-)Konstantenpool der aktuellen Klasse berechnet: (indexbyte1 << 8) | indexbyte2. Bei diesem Index befindet sich eine Konstante vom Typ Methodenreferenz. Mit Hilfe der Konstanten werden die folgenden Informationen zugänglich: Klasse, in der die Methode deklariert ist, Name der Methode, Methodendeskriptor (Anzahl und Typ der Methodenparamter, Typ des Rückgabewertes). Auf dem Operandenstapel befinden sich zunächst die Referenz auf ein Objekt
objectref einer bestimmten Klasse und die Argumente, die an
die aufzurufende Methode übergeben werden sollen. Die Argumente müssen den Vorgaben
im Methodendeskriptor genügen. Bei der Ausführung des (nicht nativen) Methodenaufrufs
werden zunächst die vorhandenen Argumente arg1, ...,
argn und die Objektreferenz vom Operandenstapel geholt und
es wird ein neuer Frame für die aufzurufende Methode erzeugt. Der Frame wird
anschließend auf dem JVM-Stack abgelegt. Der erzeugte Frame enthält einen
Operandenstapel und ein Array für die lokalen Variablen der aufgerufenen Methode.
In dieses Array werden die Objektreferenz und die übergebenen Argumente geschrieben
(falls vorhanden). Der Eintrag im Array bei Index 0 enthält die Referenz auf das
Objekt objectref und bei Index 1 ist z.B. der Wert des Arguments
arg1 abgelegt. Nachdem die Objektreferenz (Stichwort:
Beispiel: Auf der linken Seite der Übersicht steht ein Java-Quelltext, der neben einer
statischen public class Test { public class Test extends java.lang.Object { public Test() { public Test(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V int a = 1; 4: iconst_1 5: istore_1 } 6: return private void method2(int c) { private void method2(); Code: int b = c; 0: iload_1 1: istore_2 } 2: return public static void public static void main(String[] args) { main(java.lang.String[]); Code: Test t = new Test(); 0: new #2; //class Test 3: dup 4: invokespecial #3; //Method "<init>":()V 7: astore_1 t.method2(2); 8: aload_1 9: iconst_2 10: invokespecial #4; //Method method2:(I)V } 13: return } } Neben dem paramterlosen Konstruktor
Rufe eine statische Methode (Klassenmethode) auf.
Mit Hilfe der vorzeichenlosen Bytes indexbyte1 und indexbyte2 wird ein Index im (Laufzeit-)Konstantenpool der aktuellen Klasse berechnet: (indexbyte1 << 8) | indexbyte2. Bei diesem Index befindet sich eine Konstante vom Typ Methodenreferenz. Mit Hilfe der Konstanten werden die folgenden Informationen zugänglich: Klasse, in der die Methode deklariert ist, Name der Methode, Methodendeskriptor (Anzahl und Typ der Methodenparamter, Typ des Rückgabewertes). Auf dem Operandenstapel befinden sich zunächst die Argumente, die an die aufzurufende Methode übergeben werden sollen. Die Argumente müssen den Vorgaben im Methodendeskriptor genügen. Bei der Ausführung des (nicht nativen) Methodenaufrufs werden zunächst die vorhandenen Argumente arg1, ..., argn vom Operandenstapel geholt und es wird ein neuer Frame für die aufzurufende Methode erzeugt. Der Frame wird anschließend auf dem JVM-Stack abgelegt. Der erzeugte Frame enthält einen Operandenstapel und ein Array für die lokalen Variablen der aufgerufenen Methode. In dieses Array werden die übergebenen Argumente geschrieben (falls vorhanden). Der Eintrag im Array bei Index 0 enthält z.B. den Wert des Arguments arg1. Nachdem die Argumente der aufgerufenen Methode im Array für lokale Variablen zur Verfügung stehen, wird der erste Befehl (Opcode) dieser Methode aufgerufen und ausgeführt. Beispiel: Siehe dazu
Rufe eine Methode (Instanzmethode, kein Konstruktor) auf.
Mit Hilfe der vorzeichenlosen Bytes indexbyte1 und indexbyte2 wird ein Index im (Laufzeit-)Konstantenpool der aktuellen Klasse berechnet: (indexbyte1 << 8) | indexbyte2. Bei diesem Index befindet sich eine Konstante vom Typ Methodenreferenz. Mit Hilfe der Konstanten werden die folgenden Informationen zugänglich: Klasse, in der die Methode deklariert ist, Name der Methode, Methodendeskriptor (Anzahl und Typ der Methodenparamter, Typ des Rückgabewertes). Auf dem Operandenstapel befinden sich zunächst die Referenz auf ein Objekt
objectref einer bestimmten Klasse und die Argumente, die an
die aufzurufende Methode übergeben werden sollen. Die Argumente müssen den Vorgaben
im Methodendeskriptor genügen. Bei der Ausführung des (nicht nativen) Methodenaufrufs
werden zunächst die vorhandenen Argumente arg1, ...,
argn und die Objektreferenz vom Operandenstapel geholt und es
wird ein neuer Frame für die aufzurufende Methode erzeugt. Der Frame wird anschließend
auf dem JVM-Stack abgelegt. Der erzeugte Frame enthält einen Operandenstapel und
ein Array für die lokalen Variablen der aufgerufenen Methode. In dieses Array
werden die Objektreferenz und die übergebenen Argumente geschrieben (falls vorhanden).
Der Eintrag im Array bei Index 0 enthält die Referenz auf das Objekt
objectref und bei Index 1 ist z.B. der Wert des Arguments
arg1 abgelegt. Nachdem die Objektreferenz (Stichwort:
Beispiel: Auf der linken Seite der Übersicht steht ein Java-Quelltext, der neben einer
statischen public class Test { public class Test extends java.lang.Object { public Test() { public Test(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V int a = 1; 4: iconst_1 5: istore_1 } 6: return public void method2() { public void method2(); Code: int b = 2; 0: iconst_2 1: istore_1 } 2: return public static void method3() { public static void method3(); Code: int c = 3; 0: iconst_3 1: istore_0 } 2: return public static void public static void main(String[] args) { main(java.lang.String[]); Code: Test t = new Test(); 0: new #2; //class Test 3: dup 4: invokespecial #3; //Method "<init>":()V 7: astore_1 t.method2(); 8: aload_1 9: invokevirtual #4; //Method method2:()V method3(); 12: invokestatic #5; //Method method3:()V } 15: return } } Zunächst wird innerhalb der Die Klassendatei Es sind 21 Konstanten im Konstantenpool enthalten. 1. Konstante: Methode von Klasse #6, Name/Typ #17 2. Konstante: Klasse #18 3. Konstante: Methode von Klasse #2, Name/Typ #17 4. Konstante: Methode von Klasse #2, Name/Typ #19 5. Konstante: Methode von Klasse #2, Name/Typ #20 6. Konstante: Klasse #21 7. Konstante: Utf8 <init> 8. Konstante: Utf8 ()V 9. Konstante: Utf8 Code 10. Konstante: Utf8 LineNumberTable 11. Konstante: Utf8 method2 12. Konstante: Utf8 method3 13. Konstante: Utf8 main 14. Konstante: Utf8 ([Ljava/lang/String;)V 15. Konstante: Utf8 SourceFile 16. Konstante: Utf8 Test.java 17. Konstante: Name #7, Typ #8 18. Konstante: Utf8 Test 19. Konstante: Name #11, Typ #8 20. Konstante: Name #12, Typ #8 21. Konstante: Utf8 java/lang/Object
Verknüpfe zwei
Es gilt: result = value1 | value2 Beispiel: 70 | 42 = 110 int a = 70; 0: bipush 70 2: istore_1 int b = 42; 3: bipush 42 5: istore_2 int c = a | b; 6: iload_1 7: iload_2 8: ior 9: istore_3 Binäre Darstellung: 70 = (00000000 00000000 00000000 01000110)b 42 = (00000000 00000000 00000000 00101010)b 110 = (00000000 00000000 00000000 01101110)b
Berechne den
Die beiden obersten Elemente werden vom Stapel genommen und die folgende
Berechnung wird durchgeführt: result = value1 -
(value1 / value2) * value2.
Zur Berechnung von value1 / value2 siehe auch
Beispiel: 11 % 4 = 3 int a = 11; 0: bipush 11
2: istore_1
int b = 4; 3: iconst_4
4: istore_2
int c = a % b; 5: iload_1
6: iload_2
7: irem
8: istore_3 Der Inhalt der Variablen
Gebe einen
Der Rückgabewert value wird vom Stapel genommen und
an den Aufrufer der Methode zurückgegeben, indem dieser auf den Operandenstapel
des Methodenaufrufers gelegt wird. Der JVM-Befehl Beispiel 1: public class Test {
public static int method1() { public static int method1();
Code:
int a = 3; 0: iconst_3
1: istore_0
return a; 2: iload_0
} 3: ireturn
public static void main(String[] args) {
int b = method1();
}
} Beispiel 2: public class Test {
public static boolean method1() { public static boolean method1();
Code:
boolean a = true; 0: iconst_1
1: istore_0
return a; 2: iload_0
} 3: ireturn
public static void main(String[] args) {
boolean b = method1();
}
}
Verschiebe die Bits eines
Beispiel 1: 15 << 4 = 240 int a = 15; 0: bipush 15 2: istore_1 int b = 4; 3: iconst_4 4: istore_2 int c = a << b; 5: iload_1 6: iload_2 7: ishl 8: istore_3 Binäre Darstellung: 15 = (00000000 00000000 00000000 00001111)b 4 = (00000000 00000000 00000000 00000100)b 240 = (00000000 00000000 00000000 11110000)b Beispiel 2: 1073741839 << 1 = -2147483618 Binäre Darstellung: 1073741839 = (01000000 00000000 00000000 00001111)b 1 = (00000000 00000000 00000000 00000001)b -2147483618 = (10000000 00000000 00000000 00011110)b Beispiel 3: 2 << 31 = 0 Binäre Darstellung:
2 = (00000000 00000000 00000000 00000010)b
31 = (00000000 00000000 00000000 00011111)b
0 = (00000000 00000000 00000000 00000000)b
Verschiebe die Bits eines
Siehe auch Beispiel 1: 240 >> 6 = 3 int a = 240; 0: sipush 240 3: istore_1 int b = 6; 4: bipush 6 6: istore_2 int c = a >> b; 7: iload_1 8: iload_2 9: ishr 10: istore_3 Binäre Darstellung: 240 = (00000000 00000000 00000000 11110000)b 6 = (00000000 00000000 00000000 00000110)b 3 = (00000000 00000000 00000000 00000011)b Beispiel 2: -4 >> 1 = -2 Binäre Darstellung: -4 = (11111111 11111111 11111111 11111100)b 1 = (00000000 00000000 00000000 00000001)b -2 = (11111111 11111111 11111111 11111110)b
Speichere einen
Die
Speichere einen
Die
Speichere einen
Die
Speichere einen
Die
Speichere einen
Die
Subtrahiere zwei
Die beiden obersten Elemente werden vom Stapel genommen und subtrahiert: result = value1 - value2. Beispiel: int a = 2; 0: iconst_2
1: istore_1
int b = 1; 2: iconst_1
3: istore_2
int c = a - b; 4: iload_1
5: iload_2
6: isub
7: istore_3
Verschiebe die Bits eines
Siehe auch Beispiel 1: 240 >>> 6 = 3 int a = 240; 0: sipush 240 3: istore_1 int b = 6; 4: bipush 6 6: istore_2 int c = a >>> b; 7: iload_1 8: iload_2 9: iushr 10: istore_3 Binäre Darstellung: 240 = (00000000 00000000 00000000 11110000)b 6 = (00000000 00000000 00000000 00000110)b 3 = (00000000 00000000 00000000 00000011)b Beispiel 2: -4 >>> 1 = 2147483646 Binäre Darstellung: -4 = (11111111 11111111 11111111 11111100)b 1 = (00000000 00000000 00000000 00000001)b 2147483646 = (01111111 11111111 11111111 11111110)b
Verknüpfe zwei
Es gilt: result = value1 ^ value2 Beispiel: 70 ^ 42 = 108 int a = 70; 0: bipush 70 2: istore_1 int b = 42; 3: bipush 42 5: istore_2 int c = a ^ b; 6: iload_1 7: iload_2 8: ixor 9: istore_3 Binäre Darstellung: 70 = (00000000 00000000 00000000 01000110)b 42 = (00000000 00000000 00000000 00101010)b 108 = (00000000 00000000 00000000 01101100)b |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||