I have a hard time understanding how compressed pointers works in Java 19, help is appreciated.
In Java 11 the reference size is 4 for heaps below 32GiB (compressed pointers) and 8 for a larger heap. In Java 19 they seem to take 4 bytes even for larger heaps (how?).
Details:
Java versions: OpenJDK Java 11.0.12 and OpenJDK Java 19.0.1
Command lines:
-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xlog:gc -Xlog:gc+heap+coops -Xms41g -Xmx41g -XX:+AlwaysPreTouch
-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC -Xlog:gc -Xlog:gc+heap+coops -Xms31g -Xmx31g -XX:+AlwaysPreTouch
Code: https://github.com/cornelcreanga/fun/blob/master/src/main/java/com/ccreanga/various/RandomAllocate.java - the code is taken from https://shipilev.net/jvm/anatomy-quarks/23-compressed-references/
Run this code with both Java 11 and 19 and you can see that the memory size is lower in Java 19 than in Java 11 for a heap > 32 GiB. For a smaller heap the size is almost identical.
You are looking at the layout of a byte[]
array and an instance of java.lang.Object
. Neither of them contains a reference to an object inside the heap.
The difference you are seeing, is in the size of the class pointer which is not pointing to a location inside the heap memory. But for historical reasons, the option -XX:+UseCompressedClassPointers
was bound to the presence of the -XX:+UseCompressedOops
option. So when the heap size disallowed compressed object pointers, the compressed class pointers were disabled as a side effect.
JDK-8241825, Make compressed oops and compressed class pointers independent addresses this and has been solved with JDK 15.
So when I change your program to
System.out.println(ClassLayout.parseInstance(new Object[3]).toPrintable());
and run it with a 41GB heap, I get
[Ljava.lang.Object; object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)
8 8 (object header: class) 0x000001f54bec41e0
16 4 (array length) 3
20 4 (alignment/padding gap)
24 24 java.lang.Object Object;.<elements> N/A
Instance size: 48 bytes
Space losses: 4 bytes internal + 0 bytes external = 4 bytes total
prior to JDK 15 and
[Ljava.lang.Object; object internals:
OFF SZ TYPE DESCRIPTION VALUE
0 8 (object header: mark) 0x0000000000000001 (non-biasable; age: 0)
8 4 (object header: class) 0x000020fc
12 4 (array length) 3
16 24 java.lang.Object Object;.<elements> N/A
Instance size: 40 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
with JDK 15 or newer.
The difference is clearly caused by the class pointer and the padding, but the three object references require 24 bytes in each JVM version.