我正在运行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算法的阈值。
答案 0 :(得分:1)
但无法获得压缩指针优化,以便在堆大小超过32736 MB的情况下启动
这是正常的,因为默认情况下对象与8字节边界对齐,这意味着最低的3位是冗余的并且通过移位来消除,这反过来意味着32位对象指针最多可以通过该对齐来处理4GB * 8的对象
如果要使用压缩oops超过32GB,则需要通过-XX:ObjectAlignmentInBytes=16
将对象对齐到16个字节。请注意,这会使较小的对象变大,即浪费一些内存,因此您必须衡量它是否真正获得了任何东西。
This answer有一些可能感兴趣的其他诊断选项。