CMSInitiatingOccupancyFraction计算释疑

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设置为0MaxHeapFreeRatio设置为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的默认值就是40CMSInitiatingOccupancyFraction默认值就是92,百分比类型。不存在100%这样的情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值