About reference to array in Java

Viewed 107

A example in book 《Core Java Volume I》

public class Employee {
    ...
}
public class Manager extends Employee {
    ...
}
Manager[] managers = new Manager[3];
Employee[] staff = managers; //OK
staff[0] = new Employee(); //error

staff[0]will cause ArrayStoreException, beacuse the array store a wrong object. I give the memory diagram of the array: enter image description here I think variable staff store the address of staff[0](like c++, where in int *p = new int[3], variable p stores the address of the first element of the array).

Because staff is equal to managers, so they point to the same position of memory, when you write the statement staff[0] = new Employee(), I think it is equal to the statement managers[0] = new Employee(), the reference to parent points to the child object is wrong.

I'm not sure if I'm right, I hope to know the relationship of the reference to array (staff/managers) and the individual array elements (staff[0], staff[1]...), whether staff can tell me the position in memory of the first element in array.

And I would also like to know, for different arrays of objects, like Cat[] cats = new Cat[2] and Dog[] dogs = new Dog[2], whether they take up the same size in memory. Do references to different objects take up the same amount of memory?

1 Answers

I hope to know the relationship of the reference to array (staff/managers) and the individual array elements (staff[0], staff[1]...), whether staff can tell me the position in memory of the first element in array.

In Java, the individual array elements are variables within the array object, as described in section 10 in the language specification. On the language level, there are no memory addresses or pointer arithmetic. The language does not tell you if there is any relation between the memory addresses of staff[0] and staff[1] and staff - that is left up to the implementation.

As for how the implementation works, this article from Aleksey Shipilёv (the original author of JOL) is a great resource: https://shipilev.net/jvm/objects-inside-out/

In summary, the array object memory layout includes a pointer to the object's class, a "mark word" that helps with garbage collection and concurrency, the array's length (number of items), followed by the array elements themselves.

Because of the "object header", staff[0] is not at the same address as staff. But the difference is a number known to the JVM, so it can generate efficient code that uses dead reckoning to access array elements.

As for how the ArrayStoreException gets thrown: When you create an array of objects such as new Manager[3], the JVM sets the class pointer so it references the "array of Managers" class (if one doesn't already exist, it's created on the fly). When you store an object reference to the array, the JVM uses this class pointer to check whether the reference is compatible with the array component type, and throws ArrayStoreException if it's not.

Related