G1 和 CMS 的 UseCompressedOops 启动阈值不同

Ash*_*uri 3 java garbage-collection g1gc concurrent-mark-sweep

我正在运行 Oracle 的 64 位 Java 1.8 Hotspot JVM。当使用不同的 GC 机制时,我一直试图理解 JVM 的行为差异,以启动压缩对象指针。例如:

$ java -XX:+UseConcMarkSweepGC -XX:+PrintFlagsFinal -Xms32766m -Xmx32766m

bool UseCompressedClassPointers        := true        {lp64_product}
bool UseCompressedOops                 := true        {lp64_product}

$ java -XX:+UseConcMarkSweepGC -XX:+PrintFlagsFinal -Xms32767m -Xmx32767m

bool UseCompressedClassPointers        = false        {lp64_product}
bool UseCompressedOops                 = false        {lp64_product}

$ java -XX:+UseG1GC -XX:+PrintFlagsFinal -Xms32736m -Xmx32736m

bool UseCompressedClassPointers        := true        {lp64_product}
bool UseCompressedOops                 := true        {lp64_product}

$ java -XX:+UseG1GC -XX:+PrintFlagsFinal -Xms32737m -Xmx32737m

bool UseCompressedClassPointers        = false        {lp64_product}
bool UseCompressedOops                 = false        {lp64_product}
Run Code Online (Sandbox Code Playgroud)

我尝试更改其他一些 G1GC 旋钮,但无法获得压缩指针优化来启动 G1 堆大小超过 32736 MB 的情况。但是,正如您可以清楚地看到的,CMS 可以使用压缩指针来处理最大 32766 MB 的堆大小。我试图了解是什么控制着不同 GC 算法的这个阈值。

the*_*472 5

但无法让压缩指针优化在堆大小超过 32736 MB 时启动

这是正常的,因为默认情况下对象与 8 字节边界对齐,这意味着最低 3 位始终为零,并且可以通过移位消除,这又意味着 32 位对象指针最多可以使用该对齐方式寻址 4GB * 8 的对象。

-XX:ObjectAlignmentInBytes=16如果您想在压缩 oops 中使用超过 32GB 的空间,则需要将对象对齐方式提高到 16 字节。请注意,这会使小对象变大,即浪费一些内存,因此您必须衡量它是否真正为您带来了任何好处。

这个答案有一些可能令人感兴趣的额外诊断选项。