2

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?

Natasha Kurian
  • 407
  • 5
  • 11
helloWorld
  • 35
  • 7
  • 2
    Also, objects are not directly placed in arrays cells. Rather, each cell holds a reference to an object. Thus, a `Cat[]` and a `Dog[]` of same size will consume the same amount of memory since both only store references. This is why multidimensional arrays in Java are less optimized than, for example, in C: a 2-dimenional array in Java is just an array, holding references to other arrays, that hold references to objects, and all those arrays and objects can be scattered in memory. – Turing85 Aug 14 '20 at 14:00
  • 1
    Well, in short arrays store references (think of them as pointers) to objects so any array of the same length pointing to objects will have the same memory consumption in itself (assuming same bit-length etc.). As for the exception: your thoughts are correct, you get the exception because the array is actually an array of references to `Manager` instances - the type of the variable (e.g. `Employee[]`) isn't relevant here. – Thomas Aug 14 '20 at 14:04
  • You may be interested in [this article exploring one example implementation of JVM memory layout](https://www.baeldung.com/java-memory-layout) – Botje Aug 14 '20 at 14:07
  • @Botje,thank you, the answer gave me a lot of inspiration. – helloWorld Aug 15 '20 at 01:22
  • @Thomas,now I know a Cat[] and a Dog[] of same size will consume the same amount of memory since both only store references. As mentioned in my question,whether `managers` can indicate the location in memory of the first element in the array(like c++) – helloWorld Aug 15 '20 at 02:01

1 Answers1

2

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.

Joni
  • 108,737
  • 14
  • 143
  • 193
  • Thank you very much, the answer helps me a lot.I need to learn about JVM to get a deeper understanding.If I don't change the vlaue of variable `staff`, the statement `staff[0] = new Employee()` is equal to `managers[0] = new Employee()`,the reason is `staff` = `managers`,(Consider only the programmer's perspective in using these variables,No consideration of implementation or otherwise). Not sure if I'm right. – helloWorld Aug 16 '20 at 01:20
  • If `staff` and `managers` hold the same value (reference to same array object), operations on that value have the same effect no matter which variable you use. If you don't give a value for `staff` you get a compile-time error for trying to use an uninitialized variable. – Joni Aug 16 '20 at 02:25