Java G1和CMS的UseCompressedOops启动阈值不同
我正在运行Oracle提供的64位Java1.8HotSpot JVM。我一直在试图了解JVM行为的差异,以便在使用不同的GC机制时引入压缩对象指针。例如:Java G1和CMS的UseCompressedOops启动阈值不同,java,garbage-collection,g1gc,concurrent-mark-sweep,Java,Garbage Collection,G1gc,Concurrent Mark Sweep,我正在运行Oracle提供的64位Java1.8HotSpot JVM。我一直在试图了解JVM行为的差异,以便在使用不同的GC机制时引入压缩对象指针。例如: $ java -XX:+UseConcMarkSweepGC -XX:+PrintFlagsFinal -Xms32766m -Xmx32766m bool UseCompressedClassPointers := true {lp64_product} bool UseCompressedOops
$ 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的堆大小超过32736MB时启动。但是,正如您可以清楚地看到的,CMS可以使用压缩指针处理高达32766MB的堆。我试图了解是什么控制了不同GC算法的阈值
但无法让压缩指针优化在堆大小超过32736MB时启动
这是正常的,因为默认情况下对象与8字节边界对齐,这意味着最低3位是冗余的,并通过移位消除,这反过来意味着32位对象指针最多可以通过这种对齐方式寻址4GB*8的对象
如果要使用超过32GB的压缩OOP,则需要通过-XX:ObjectAlignmentInBytes=16将对象对齐增加到16字节。请注意,这会使小对象变大,即浪费一些内存,因此您必须测量它是否确实为您带来了任何好处
有一些可能感兴趣的附加诊断选项。最后一个命令-XX:+G1GC
中的G1标志是打字错误吗?@IceMan是的,谢谢你指出。我刚刚纠正了,就是这样。我使用的堆容量不超过32GB。32766 MB和32736 MB都小于32 GB。CMS使用压缩指针直到32766MB,而G1只使用压缩指针直到32736MB。我无法理解这些阈值之间的差异是什么原因。(对问题进行了编辑,以清楚地反映我的困惑。)为什么这一微小的差异甚至很重要?无论如何,我链接的答案包含诊断标志,它们可能有助于解决您的“问题”。