This is an old revision of the document!
The following figure demonstrates how arrays are implemented in the memory.
An array extends java/lang/object. The field Tag points to the type descriptor of this array ([ClassA for this example). The single array elements themselves are of type ClassA and have a Tag which points to the type descriptor of ClassA. For this reason arrays of base types like ([B, [S …) need a einen class descritor as well.
The field length denotes the number of elements of the array (16 bit). heap is used for the garbage collection (Heap Manager and Garbage Collection). In between there is a byte which contains an array bit. This is used for type checking. The P bit is for garbage collection. It is set for arrays of primitive types
When accessing array elements the code generator inserts code to check if the element index is in the range 0 to length.
If the field length is used in Java the Bytecode instruktion arraylength is used. This instruktion has to be translated such as the length field is accessed.
The Java code
static int[]a1 = new int[4];
will be translated into Bytecode
0 iconst_4 1 newarray int 3 putstatic Test.a1 : int[]
When regular objects are created the constructor of the supertype is automatically inserted into the Bytecode. When arrays are created there is no such call. The constructor of Object has to be inserted by the code generator and the heap manager has to add the size of java/lang/Object to the size of the array. As long as java/lang/Object has no fields the size is 0 and we can also omit the call of the constructor.
In the Bytecode newarray has a type (here int). When generating the SSA the reference to this type [I has to be fetched from the object directory.
For
static Object[] a1 = new ClassA[4];
the Bytecode looks like:
0 iconst_4 1 anewarray ch/ntb/junitTarget/comp/objects/ClassA 4 putstatic ch/ntb/junitTarget/comp/objects/InheritanceTest.a1: Ljava/lang/Object[];
Here, as well, the reference to [ClassA has to be fetched from the object directory when generating the SSA. There are cases when there is no entry for [ClassA. This is the case when there is never a type check for the type [ClassA. Then the SSA has a reference to null and the Tag can be 0 as well.
Betrachten wir den folgenden Fall
int[][] a = new int[2][3]
Im Speicher ergibt sich folgende Situation
[[I und [I sind die entsprechenden Typdescriptoren. Bei einem Arrayzugriff muss also zuerst in der ersten Dimension eine Referenz geladen werden und damit ein zweiter Arrayzugriff gemacht werden.
Der folgende Code
short[][] a = new short[2][3]
führt auf den Bytecode
0 iconst_2 1 iconst_3 2 multianewarray short[][] 6 putstatic ch/ntb/inf/deep/runtime/mpc555/test/ArrayTest3.a1: short[][]
Wenn aber ein Array gleich initialisiert wird, z.B. mit
short[][] a2 = {{1,2},{3,4}};
führt das auf den Bytecode
9 iconst_2 10 anewarray [S 13 dup 14 iconst_0 15 iconst_2 16 newarray short 18 dup 19 iconst_0 20 iconst_1 21 sastore 22 dup 23 iconst_1 24 iconst_2 25 sastore 26 aastore 27 dup 28 iconst_1 29 iconst_2 30 newarray short usw.
Das Problem ist im ersten Fall, dass nur der Typdescriptor von [[I gelinkt würde. [I muss ebenfalls erzeugt werden. Im Heapmanager muss die Methode multianewarray das Array allozieren und insbesondere auch die Referenzen auf [[I und [I setzen. Die Referenz auf [[I wird als Parameter übergeben. Im Typdescriptor von [[I steht die Referenz auf [I. Die muss dort geholt werden und am richtigen Ort im Object gespeichert werden.
Die gleichen Überlegungen gelten auch für Arrays mit höheren Dimensionen. Auch dort wird multianewarray nur in besonderen Situationen verwendet.
Hier gelten grundsätzlich die gleichen Bedingungen wie oben. Der folgende Javacode
ClassA[][][] a1 = new ClassA[3][2][2];
wird in den Bytecode
0 iconst_3 1 iconst_2 2 iconst_2 3 multianewarray Lch/ntb/junitTarget/comp/arrays/A[][][]; 7 astore_1 [a1]
übersetzt. Hier wird also bereits also bereits die korrekte Referenz auf [[[ClassA; in die SSA aufgenommen. Der Heapmanager muss wie bei den Basistypen aus dem Typdescriptor von [[[ClassA; die weiteren Typdescriptoren [[ClassA;, [ClassA; und ClassA; rekursiv holen.