javaseiten.de   |   Version 0.6
 

4.16. JVM-Befehlssatz: Kurzbeschreibung N

 

 

Befehl Operandenstapel Opcode
new indexbyte1 indexbyte2 ... --> ..., objectref 0xbb

Erzeuge ein neues Objekt.

Bezeichner Typ Beschreibung
indexbyte1 Vorzeichenloses Byte Index im (Laufzeit-)Konstantenpool.
indexbyte2 Vorzeichenloses Byte Index im (Laufzeit-)Konstantenpool.
objectref reference Referenz auf das neu erzeugte Objekt.

Mit Hilfe der vorzeichenlosen Bytes indexbyte1 und indexbyte2 wird ein Index im (Laufzeit-)Konstantenpool der aktuellen Klasse berechnet: (indexbyte1 << 8) | indexbyte2. Mit Hilfe dieses Index kann die Klasse ermittelt werden, von der ein Objekt erzeugt werden soll. Die Erzeugung eines neuen Objekts erfolgt mit Hilfe des JVM-Befehls new und dem Aufruf von Methoden zur Initialisierung der Klasse (statischer Initialisierer) und des Objekts (Konstruktor). Im Gegensatz zu Konstruktoraufrufen, die mit dem Befehl invokespecial erfolgen können, werden Initialisierungsmethoden für Klassen automatisch durch die virtuelle Java-Maschine vorgenommen (sie werden nicht explizit durch einen JVM-Befehl aufgerufen).

Beispiel 1:

Die folgenden Programmausschnitte aus einem Quelltext bzw. auf Bytecodeebene erzeugen ein neues Objekt der Klasse String:

public class Test {

  public static void               public static void main(java.lang.String[]);
  main(String[] args) {            Code:

    String s = new String();       0: new #2; //class java/lang/String
                                   3: dup
                                   4: invokespecial #3; 
                                      //Method java/lang/String."<init>":()V
                                   7: astore_1
  }                                8: return
}

Die Angabe #2 aus new #2 resultiert aus den beiden Indexbytes und steht für die 2. Konstante im (Laufzeit-)Konstantenpool. Die einzelnen Konstanten aus dem Pool der zum Quelltext gehörenden Klassendatei Test.class können dabei wie folgt angegeben werden:

Es sind 17 Konstanten im Konstantenpool enthalten.
1. Konstante: Methode von Klasse #5, Name/Typ #14
2. Konstante: Klasse #15
3. Konstante: Methode von Klasse #2, Name/Typ #14
4. Konstante: Klasse #16
5. Konstante: Klasse #17
6. Konstante: Utf8 <init>
7. Konstante: Utf8 ()V
8. Konstante: Utf8 Code
9. Konstante: Utf8 LineNumberTable
10. Konstante: Utf8 main
11. Konstante: Utf8 ([Ljava/lang/String;)V
12. Konstante: Utf8 SourceFile
13. Konstante: Utf8 Test.java
14. Konstante: Name #6, Typ #7
15. Konstante: Utf8 java/lang/String
16. Konstante: Utf8 Test
17. Konstante: Utf8 java/lang/Object

Die 2. Konstante verweist zum UTF8-String "java/lang/String", der die Klasse repräsentiert, von der ein neues Objekt erzeugt werden soll. Die zu dieser Zeichenkette korrespondierende Klassendatei String.class befindet sich im Archiv rt.jar, welches z.B. im Ordner c:\jdk1.x.x\jre\lib\ abgespeichert ist. Nach Ausführung von new #2 befindet sich die Referenz auf dieses Objekt objectref auf dem Operandenstapel. Mit dup wird der oberste Wert auf dem Stapel verdoppelt: ..., objectref --> ..., objectref, objectref. Dies ist nötig, da der Befehl invokespecial eine Referenz vom Stapel nimmt und für astore_1 noch eine Objektreferenz benötigt wird. Mit invokespecial #3 wird der parameterlose Konstruktor der Klasse String aufgerufen (siehe 3. Konstante im Konstantenpool) und mit dem letzten JVM-Befehl erfolgt die Zuweisung der erzeugten Objektreferenz an die Objektvariable s.

Beispiel 2:

Die folgende Übersicht zeigt die Verwendung eines Konstruktors und eines statischen Initialisierers auf Bytecodeebene:

public class Test {                   public class Test 
                                      extends java.lang.Object {

                                      public Test();
                                      Code:
                                       0: aload_0
                                       1: invokespecial #1; //Method 
                                          java/lang/Object."<init>":()V
                                       4: return

                                      static {};
                                      Code:
  static int a = 3;                    0: iconst_3
                                       1: putstatic #4; //Field a:I
                                       4: return

  public static void                  public static void
  main(String[] args) {               main(java.lang.String[]);
                                      Code:
    int b = 0;                         0: iconst_0
                                       1: istore_1                            
    Test t = new Test();               2: new #2; //class Test
                                       5: dup
                                       6: invokespecial #3; //Method 
                                          "<init>":()V
                                       9: astore_2
    b = a;                            10: getstatic #4; //Field a:I
                                      13: istore_1
  }                                   14: return

}                                     }

Durch die Anweisungen new #2 und invokespecial #3 wird ein neues Objekt der Beispielklasse Test erzeugt und initialisiert. Die Initialisierung erfolgt durch Aufruf eines sogenannte Default-Konstruktors. Im Beispiel wird der parameterlose Default-Konstruktor pulic Test() vom Compiler automatisch erzeugt, da kein Konstruktor im Quelltext explizit deklariert wurde. Der Default-Konstruktor hat die Aufgabe den parameterlosen Konstruktor der Superklasse aufzurufen (die Superklasse von Test ist definitionsgemäß die Wurzelklasse Object der Klassenhierarchie).

Die Deklaration und Initialisierung der Klassenvariablen a durch static int a = 3; könnte auch mit Hilfe eines statischen Initialisierers im Quelltext erfolgen:

static int a;
static {
  a = 3;
}

Die durch den Compiler erzeugten Befehle auf Bytecodeebene unterscheiden sich dadurch nicht.

 

 

newarray atype ..., count --> ..., arrayref 0xbc

Erzeuge ein neues Array (für primitive Datentypen).

Bezeichner Typ Beschreibung
atype Vorzeichenloses Byte Typ des Arrays.
count int Anzahl der Array-Elemente.
arrayref reference Referenz auf das neu erzeugte Array.

Der Typ des Arrays atype ist durch einen Zahlenwert codiert:

Typ des Arrays atype
T_BOOLEAN 4
T_CHAR 5
T_FLOAT 6
T_DOUBLE 7
T_BYTE 8
T_SHORT 9
T_INT 10
T_LONG 11

Für das neu erzeugte Array wird Speicherplatz vom Heap bereitgestellt und jedes Element des Arrays wird abhängig vom Typ mit einem Standardwert initialisiert. Zur Erzeugung von Arrays für Referenztypen siehe anewarray.

Beispiel:

Im Beispiel wird zunächst ein int-Array mit 3 Elementen erzeugt. Anschließend wird das Element bei Index 0 mit dem Zahlenwert 4 initialisiert.

int[] i = new int[3];        0: iconst_3
                             1: newarray int;
                             3: astore_1
i[0] = 4;                    4: aload_1
                             5: iconst_0 
                             6: iconst_4
                             7: iastore

Der JVM-Befehl newarray int wird innerhalb einer zum Quelltext gehörenden Klassendatei mit den beiden Bytes bc 0a codiert. Das erste Byte ist der Operationscode für den Befehl und das Operandenbyte 0a gibt den Typ des zu erzeugenden neuen Arrays an. Der dezimale Wert des Operandenbytes ist 10 und der Typ der Elemente des Arrays ist damit int.

 

 

nop ... --> ... 0x00

Dieser JVM-Befehl führt keine Operation aus (no operation).

 

 

 

Diese Seite nutzt Google-Dienste - siehe dazu Datenschutz.

Copyright © 2006, 2007 Harald Roeder