java - G1 和 CMS 的 UseCompressedOops 启动阈值不同

标签 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}

我尝试更改其他一些 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/

相关文章:

garbage-collection - 为什么垃圾收集器在分配之前要等待?

C# 终结器不释放非托管内存

Java SoftReference、 panic GC 和 GC 行为

java - 计算十进制值的双邻居

java - 异常处理错误 : cannot find symbol variable

garbage-collection - 我可以在性能监视器中使用哪个计数器来查看有多少内存正在等待 GC?

java - 后续: G1 Collector not doing full GC

java - 捕获所有 Tomcat (GWT) servlet 中所有未处理异常的最佳方法

java - 如何使用 Log4J 掩盖日志文件中的信用卡号?

java - G1 old generation committed 内存突然增加,Eden size 减少