[英]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 -夸克/23-压缩参考/
使用 Java 11 和 19 运行这段代码,您可以看到 Java 19 中的 memory 大小小于 Java 11 中的堆 > 32 GiB。 对于较小的堆,大小几乎相同。
您正在查看byte[]
数组的布局和java.lang.Object
的实例。 它们都不包含对堆内 object 的引用。
您看到的差异在于class 指针的大小,它未指向堆 memory 内的某个位置。但是由于历史原因,选项-XX:+UseCompressedClassPointers
绑定到-XX:+UseCompressedOops
的存在选项。 因此,当堆大小不允许压缩 object 指针时,作为副作用,压缩的 class 指针将被禁用。
JDK-8241825,使压缩的 oops 和压缩的 class 指针独立解决这个问题,并已通过 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 或更新版本。
差异显然是由 class 指针和填充引起的,但是三个 object 引用在每个 JVM 版本中需要 24 个字节。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.