提问人:Cornel Creanga 提问时间:11/6/2022 最后编辑:Mark RotteveelCornel Creanga 更新时间:11/26/2022 访问量:345
OpenJDK 19 和压缩指针
OpenJDK 19 and compressed pointers
问:
我很难理解压缩指针在 Java 19 中是如何工作的,非常感谢帮助。
在 Java 11 中,对于低于 32GiB(压缩指针)的堆,引用大小为 4,对于较大的堆,引用大小为 8。在 Java 19 中,即使对于较大的堆,它们似乎也需要 4 个字节(如何?
详:
Java 版本:OpenJDK Java 11.0.12 和 OpenJDK Java 19.0.1
命令行:
-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
代码:https://github.com/cornelcreanga/fun/blob/master/src/main/java/com/ccreanga/various/RandomAllocate.java - 代码取自 https://shipilev.net/jvm/anatomy-quarks/23-compressed-references/
使用 Java 11 和 19 运行此代码,您可以看到 Java 19 中的内存大小低于 Java 11 中的内存大小,堆> 32 GiB。对于较小的堆,大小几乎相同。
答:
您正在查看数组的布局和 的实例。它们都不包含对堆内对象的引用。byte[]
java.lang.Object
您看到的区别在于类指针的大小,该指针不指向堆内存中的位置。但由于历史原因,该选项与该选项的存在有关。因此,当堆大小不允许使用压缩对象指针时,压缩类指针会被禁用作为副作用。-XX:+UseCompressedClassPointers
-XX:+UseCompressedOops
JDK-8241825,使压缩的 oops 和压缩的类指针独立解决此问题,并已在 JDK 15 中解决。
所以当我把你的程序改成
System.out.println(ClassLayout.parseInstance(new Object[3]).toPrintable());
并使用 41GB 的堆运行它,我得到
[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
JDK 15 之前的版本和
[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
使用 JDK 15 或更高版本。
这种差异显然是由类指针和填充引起的,但三个对象引用在每个 JVM 版本中都需要 24 个字节。
评论