JVM CMS垃圾收集器相关一个重要参数CMSInitiatingOccupancyFraction
,默认值具体是多少,众说纷纭,这里分析和验证一下。
-XX:CMSInitiatingOccupancyFraction
: 当老年代使用达到该比例时会触发FullGC,百分比格式。
1. 计算CMSInitiatingOccupancyFraction
具体还是要看openJDK的代码(基于JDK8):
// hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
// The field "_initiating_occupancy" represents the occupancy percentage
// at which we trigger a new collection cycle. Unless explicitly specified
// via CMSInitiatingOccupancyFraction (argument "io" below), it
// is calculated by:
//
// Let "f" be MinHeapFreeRatio in
//
// _intiating_occupancy = 100-f +
// f * (CMSTriggerRatio/100)
// where CMSTriggerRatio is the argument "tr" below.
//
// That is, if we assume the heap is at its desired maximum occupancy at the
// end of a collection, we let CMSTriggerRatio of the (purported) free
// space be allocated before initiating a new collection cycle.
//
void ConcurrentMarkSweepGeneration::init_initiating_occupancy(intx io, uintx tr) {
assert(io <= 100 && tr <= 100, "Check the arguments");
if (io >= 0) {
_initiating_occupancy = (double)io / 100.0;
} else {
_initiating_occupancy = ((100 - MinHeapFreeRatio) +
(double)(tr * MinHeapFreeRatio) / 100.0)
/ 100.0;
}
}
其中:
io
参数是:输入的CMSInitiatingOccupancyFraction
值
tr
参数是:CMSTriggerRatio
的值,JDK8默认是80
代码逻辑比较简单:
- 若指定的
CMSInitiatingOccupancyFraction
为正值,例如80,则老年代到达80%就会触发FullGC。 CMSInitiatingOccupancyFraction
默认为-1,走下面的分支。
基于JDK8,结合其余2个参数MinHeapFreeRatio
默认值40、CMSTriggerRatio
默认值80,计算出的默认百分比是92
。
若MinHeapFreeRatio
默认值0、CMSTriggerRatio
默认值80,则计算出的默认百分比是100
。
2. MinHeapFreeRatio的默认值到底是多少?0还是40?
这里有个疑问点:MinHeapFreeRatio
的默认值到底是多少?0还是40?
通过-XX:+PrintFlagsFinal
参数打印出来的MinHeapFreeRatio默认值是0
:
uintx MinHeapFreeRatio = 0 {manageable}
再借助jinfo -flag MinHeapFreeRatio PID
打印出来的MinHeapFreeRatio
默认值都是0
。
C:\Users\root>jinfo -flag MinHeapFreeRatio 18896
-XX:MinHeapFreeRatio=0
但是从源码上看MinHeapFreeRatio
默认值从JDK6开始默认值就一直是40
了。
// hotspot/src/share/vm/runtime/globals.hpp
manageable(uintx, MinHeapFreeRatio, 40, \
"The minimum percentage of heap free after GC to avoid expansion."\
" For most GCs this applies to the old generation. In G1 and" \
" ParallelGC it applies to the whole heap.") \
\
manageable(uintx, MaxHeapFreeRatio, 70, \
"The maximum percentage of heap free after GC to avoid shrinking."\
" For most GCs this applies to the old generation. In G1 and" \
" ParallelGC it applies to the whole heap.")
说明MinHeapFreeRatio
在哪里进行修改了!
查了一下openJDK相关的代码,发现有这个UseAdaptiveSizePolicy
配置,打开时,会默认将MinHeapFreeRatio
设置为0
,MaxHeapFreeRatio
设置为100
。
而UseAdaptiveSizePolicy
默认就是开启的!这也就能解释为什么代码中默认值是40,而实际运行PrintFlagsFinal时则是0。
bool UseAdaptiveSizePolicy = true {product}
// hotspot/src/share/vm/runtime/arguments.cpp
if (UseAdaptiveSizePolicy) {
// We don't want to limit adaptive heap sizing's freedom to adjust the heap
// unless the user actually sets these flags.
if (FLAG_IS_DEFAULT(MinHeapFreeRatio)) {
FLAG_SET_DEFAULT(MinHeapFreeRatio, 0);
_min_heap_free_ratio = MinHeapFreeRatio;
}
if (FLAG_IS_DEFAULT(MaxHeapFreeRatio)) {
FLAG_SET_DEFAULT(MaxHeapFreeRatio, 100);
_max_heap_free_ratio = MaxHeapFreeRatio;
}
}
关闭UseAdaptiveSizePolicy
,然后再查看MinHeapFreeRatio
:
java -XX:+PrintFlagsFinal -XX:-UseAdaptiveSizePolicy -version | grep MinHeapFreeRatio
结果符合预期了:
uintx MinHeapFreeRatio = 40 {manageable}
3. UseAdaptiveSizePolicy和CMS
从网上查阅到的信息是,对于JDK8,当启用CMS时,无论UseAdaptiveSizePolicy
设置成什么值,都会关闭UseAdaptiveSizePolicy
,自然而然MinHeapFreeRatio
就不会被调整为0了。
java -XX:+PrintFlagsFinal -XX:+UseConcMarkSweepGC -version | grep -E "MinHeapFreeRatio | UseAdaptiveSizePolicy"
java -XX:+PrintFlagsFinal -XX:+UseConcMarkSweepGC -XX:+UseAdaptiveSizePolicy -version | grep -E "MinHeapFreeRatio | UseAdaptiveSizePolicy"
结果符合预期:UseAdaptiveSizePolicy
关闭,且MinHeapFreeRatio
变为默认值40
。
uintx MinHeapFreeRatio = 40 {manageable}
bool UseAdaptiveSizePolicy = false {product}
Java HotSpot(TM) 64-Bit Server VM warning: disabling UseAdaptiveSizePolicy; it is incompatible with UseConcMarkSweepGC.
uintx MinHeapFreeRatio = 40 {manageable}
bool UseAdaptiveSizePolicy := false {product}
4. 结论
对于JDK6/JDK7/JDK8,CMS的参数:CMSInitiatingOccupancyFraction
,肯定需要启用CMS(-XX:+UseConcMarkSweepGC
),此时UseAdaptiveSizePolicy
会强制关闭,所以MinHeapFreeRatio
的默认值就是40
,CMSInitiatingOccupancyFraction
默认值就是92
,百分比类型。不存在100%这样的情况。