Arrays

The following figure demonstrates how arrays are implemented in the memory.

Implementation of an array

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 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 so that the length field is accessed.

Generating Arrays

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 org/deepjava/junitTarget/comp/objects/ClassA
  4  putstatic org/deepjava/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.

Multidimensional Arrays

Let us consider the following case:

int[][] a = new int[2][3]

The memory will look like

2-dimensional Array

[[I and [I are the corresponding type descriptors. When accessing an element one has to access a reference in the first dimension followed by the element access in the second dimension.

Generating an Multidimensional Array of Basetypes

The following code

  short[][] a = new short[2][3]

leads to the Bytecode

0 iconst_2
1 iconst_3
2 multianewarray short[][]
6 putstatic org/deepjava/runtime/mpc555/test/ArrayTest3.a1: short[][]

If an array is immediately initialized

  short[][] a2 = {{1,2},{3,4}};

the Bytecode will be

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
etc.

The problem with the first case is, that only the type descriptor [[I would be linked. However, [I must be created as well. In the method multianewarray of the heap manager the array must be allocated and the references to [[I and [I must be set. The reference to [[I is passed as a parameter. In [[I there is the reference to [I. This reference must be fetched and inserted into the object at the appropriate position.
Similar thoughts are true for arrays with higher dimensions. As well, the instruction multianewarray is used solely for special purposes.

Generating an Multidimensional Array of Objects

Here, the same conditions are true as described above.

  ClassA[][][] a1 = new ClassA[3][2][2];

This leads to Bytecode

  0 iconst_3
  1 iconst_2
  2 iconst_2
  3 multianewarray Lch/ntb/junitTarget/comp/arrays/A[][][];
  7 astore_1 [a1]

The reference to [[[ClassA; can be found already in the SSA. The heap manager has to fetch the base types [[ClassA;, [ClassA; and ClassA; from the type descriptor recursively.