背景
在使用jmap,查看堆内存分配情况时,发现一个奇怪的现象,Eden跟Survivor的比例并不是按照8:1:1的比例分配。
使用 jmap -heap pid
可以看到NewRatio=2 实际Eden:Old=74M:148M=1:2 符合预期。
SurvivorRatio=8 按照预期Eden:S0:S1=8:1:1
Eden | S0 | S1 | |
---|---|---|---|
预期 | 62,075,699B | 7,759,462B | 7,759,462B |
实际 | 58,720,256B | 9,437,184B | 9,437,184B |
Eden 比预期偏小S0、S1比预期大。
查看官方文档
大意如下:
设置吞吐量垃圾收集器使用的初始生存空间比率(-XX:+UseParallelGC和或-XX:+UseParallelOldGC选项启用)。默认情况下,通过使用-XX:+UseParallelGC和-XX:+UseParallelOldGC选项,通过吞吐量垃圾收集器启用自适应调整大小,并根据应用程序行为从初始值开始调整生存空间的大小。如果禁用了自适应大小调整(使用-XX:UseAdaptiveSizePolicy选项),则应使用-XX:SivitorRatio选项为应用程序的整个执行设置幸存者空间的大小。
可以看到影响S0、S1的大小跟jvm使用的垃圾收收集器有关,查看进程jvm参数,可以看到确实使用了-XX:+UseParallelGC,要恢复默认的比例,需要关闭UseAdaptiveSizePolicy选项,同时显式加参数-XX:SivitorRatio=8。
VM Flags:
Non-default VM flags:
-XX:CICompilerCount=12
-XX:InitialHeapSize=232783872
-XX:MaxHeapSize=3720347648
-XX:MaxNewSize=1239941120
-XX:MinHeapDeltaBytes=524288
-XX:NewSize=77594624
-XX:OldSize=155189248
-XX:+UseCompressedClassPointers
-XX:+UseCompressedOops
-XX:+UseFastUnorderedTimeStamps
-XX:-UseLargePagesIndividualAllocation
-XX:+UseParallelGC
按照官方提示,启动参数加上
-XX:-UseAdaptiveSizePolicy -XX:SurvivorRatio=8
可见,此时Eden:S0:S1=8:1:1