In the Java® Virtual Machine Specification, section 2.7 Representation of Objects, it says :
In some of Oracle’s implementations of the Java Virtual Machine, a reference to a class instance is a pointer to a handle that is itself a pair of pointers: one to a table containing the methods of the object and a pointer to the Class object that represents the type of the object, and the other to the memory allocated from the heap for the object data.
I have the impression that the handle has three pointers instead of two :
Could anyone please clear up this confusion for me.
First of all, the quoted text says "In some of Oracle’s implementations of the Java Virtual Machine ...". This description is not correct for all implementations.
It think your misunderstanding is based on a mis-parsing of the text. What I think it is actually saying is this:
Class
object.The handle has two pointers, not three.
My understanding is that in modern Oracle JVMs, the representation of a handle is as follows:
Class
object. It also gives the size (in words) of an instance's data area that the GC needs.The representation for arrays is a bit different. For a start, there is a 3rd word containing the array length.
(See also What is in java object header)
But note that these details are implementation specific. Particularly the flag word.
In terms of how the Oracle is actually implemented is just a detail which isn't specified. A reference is a pointer (possibly compressed, see Compressed Oops) to the object's header and data.
In the header is a pointer to the class definition. You can see this using Unsafe. In this case, I have assumed compressed oops have to be turned off to keep things simple.
WARNING This is not suitable for work, only try this at home. ;)
When run on Oracle Java 8. Another JVM version might be different.
Object i = 0x12345678;
// set the System.identityHashCode
UNSAFE.putInt(i, 1L, 0x23456789);
System.out.printf("identityHashCode: %x%n", System.identityHashCode(i));
Object[] obj = {i};
assert Unsafe.ARRAY_OBJECT_INDEX_SCALE == 8; // 8 bytes per reference.
long address = UNSAFE.getLong(obj, (long) Unsafe.ARRAY_OBJECT_BASE_OFFSET);
System.out.printf("address: %x%n", address);
for (int j = 0; j < 24; j++)
System.out.printf("%02x ", UNSAFE.getByte(address + j) & 0xFF);
System.out.println();
System.out.printf("`i` is a %s and is %x%n", i.getClass(), i);
// now some really scary sh!t
long longClassPointer = UNSAFE.getLong(0L, 8L);
UNSAFE.putLong(i, 8L, longClassPointer);
System.out.printf("`i` is now a %s and is %x%n", i.getClass(), i);
prints the hashCode set, the 64-bit address, the contents of the object and header, and finally what happens if you change the klass pointer to that of a Long class instead.
identityHashCode: 23456789
address: 1d3f9ca00
01 89 67 45 23 00 00 00 a0 74 f8 26 00 00 00 00 78 56 34 12 00 00 00 00
`i` is a class java.lang.Integer and is 12345678
`i` is now a class java.lang.Long and is 12345678
for the complete code https://github.com/peter-lawrey/Performance-Examples/blob/master/src/main/java/vanilla/java/unsafe/AccessRawMemoryMain.java
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With