OpenJDK 19 and compressed pointers
Asked Answered
P

1

8

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.

Parental answered 5/11, 2022 at 19:24 Comment(1)
basically a duplicate of thisSeverson
C
8

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.

Choke answered 7/11, 2022 at 15:56 Comment(1)
Thanks for the explanation. I will also add a link that might be usefull for someone in future stuefe.de/posts/metaspace/what-is-compressed-class-spaceParental

© 2022 - 2024 — McMap. All rights reserved.