我正在运行 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}
我尝试更改其他一些 G1GC 旋钮,但无法获得压缩指针优化来启动 G1 堆大小超过 32736 MB 的情况。但是,正如您可以清楚地看到的,CMS 可以使用压缩指针来处理最大 32766 MB 的堆大小。我试图了解是什么控制着不同 GC 算法的阈值。
最佳答案
but cannot get it compressed pointer optimization to kick in for heap sizes above 32736 MB
这是正常的,因为默认情况下对象与 8 字节边界对齐,这意味着最低 3 位始终为零,并且可以通过移位消除,这又意味着 32 位对象指针最多可以寻址 4GB * 8 的对象对齐。
如果您想在压缩 oops 中使用超过 32GB 的空间,则需要通过 -XX:ObjectAlignmentInBytes=16
将对象对齐调整为 16 字节。请注意,这会使小对象变大,即浪费一些内存,因此您必须衡量它是否真正为您带来了任何东西。
This answer有一些您可能感兴趣的附加诊断选项。
关于java - G1 和 CMS 的 UseCompressedOops 启动阈值不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38752782/