OpenJDK 19与压缩指针

8

我很难理解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运行此代码,您会发现对于大于32 GiB的堆,Java 19的内存占用量比Java 11低。对于较小的堆,大小几乎相同。


2
基本上是这个:在JDK 13中,默认启用了UseCompressedOops和UseCompressedClassPointers选项(用于压缩对象指针和类指针以节省内存)。在JDK 15中,这些选项仍然默认启用,但建议使用-Zero来代替它们。使用-Zero将自动启用这些选项,并且还启用了其他一些性能优化。 - Eugene
1个回答

8
您正在查看一个 byte[] 数组和一个 java.lang.Object 实例的布局。它们都不包含指向堆内对象的引用。
您看到的区别在于 类指针 的大小,它并不指向堆内存中的位置。但由于历史原因,选项 -XX:+UseCompressedClassPointers 与选项 -XX:+UseCompressedOops 的存在绑定在一起。所以当堆大小不允许压缩对象指针时,压缩类指针会作为附带效果被禁用。 JDK-8241825, Make compressed oops and compressed class pointers independent 解决了这个问题,并已在 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字节。


2
谢谢您的解释。我还会添加一个链接,可能对未来的某个人有用 https://stuefe.de/posts/metaspace/what-is-compressed-class-space/ - Cornel Creanga

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接