JVM 源码解读之 CMS GC 触发条件

本文详细解析了JVM中CMS垃圾收集器的触发条件,包括foreground collector和background collector。触发因素不仅限于CMSInitiatingOccupancyFraction阈值,还包括Old Gen使用率、Metaspace状态、Young GC失败风险等。理解这些条件有助于解决实际遇到的CMS GC问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

点击上方"涤生的博客",关注我

转载请注明原创出处,谢谢! 如果读完觉得有收获的话,欢迎点赞加关注。

前言

经常有同学会问,为啥我的应用 Old Gen 的使用占比没达到 CMSInitiatingOccupancyFraction 参数配置的阈值,就触发了 CMS GC,表示很莫名奇妙,不知道问题出在哪?

其实 CMS GC 的触发条件非常多,不只是 CMSInitiatingOccupancyFraction 阈值触发这么简单。本文通过源码全面梳理了触发 CMS GC 的条件,尽可能的帮你了解平时遇到的奇奇怪怪的 CMS GC 问题。

先抛出一些问题,来吸引你的注意力。

为什么 Old Gen 使用占比仅 50% 就进行了一次 CMS GC? Metaspace 的使用也会触发 CMS GC 吗? 为什么 Old Gen 使用占比非常小就进行了一次 CMS GC?

触发条件

CMS GC 在实现上分成 foreground collector 和 background collector。foreground collector 相对比较简单,background collector 比较复杂,情况比较多。

下面我们从 foreground collector 和 background collector 分别来说明他们的触发条件:

说明:本文内容是基于 JDK 8 说明:本文仅涉及 CMS GC 的触发条件,至于算法的具体过程,以及什么时候进行 MSC(mark sweep compact)不在本文范围

foreground collector

foreground collector 触发条件比较简单,一般是遇到对象分配但空间不够,就会直接触发 GC,来立即进行空间回收。采用的算法是 mark sweep,不压缩。

background collector

说明 background collector 的触发条件之前,先来说下 background collector 的流程,它是通过 CMS 后台线程不断的去扫描,过程中主要是判断是否符合 background collector 的触发条件,一旦有符合的情况,就会进行一次 background 的 collect。

void ConcurrentMarkSweepThread::run() {	
  ...//省略	
  while (!_should_terminate) {	
    sleepBeforeNextCycle();	
    if (_should_terminate) break;	
    GCCause::Cause cause = _collector->_full_gc_requested ?	
      _collector->_full_gc_cause : GCCause::_cms_concurrent_mark;	
    _collector->collect_in_background(false, cause);	
  }	
  ...//省略	
}

每次扫描过程中,先等 CMSWaitDuration 时间,然后再去进行一次 shouldConcurrentCollect 判断,看是否满足 CMS background collector 的触发条件。CMSWaitDuration 默认时间是 2s(经常会有业务遇到频繁的 CMS GC,注意看每次 CMS GC 之间的时间间隔,如果是 2s,那基本就可以断定是 CMS 的 background collector)。

void ConcurrentMarkSweepThread::sleepBeforeNextCycle() {	
  while (!_should_terminate) {	
    if (CMSIncrementalMode) {	
      icms_wait();	
      if(CMSWaitDuration >= 0) {	
        // Wait until the next synchronous GC, a concurrent full gc	
        // request or a timeout, whichever is earlier.	
        wait_on_cms_lock_for_scavenge(CMSWaitDuration);	
      }	
      return;	
    } else {	
      if(CMSWaitDuration >= 0) {	
        // Wait until the next synchronous GC, a concurrent full gc	
        // request or a timeout, whichever is earlier.	
        wait_on_cms_lock_for_scavenge(CMSWaitDuration);	
      } else {	
        // Wait until any cms_lock event or check interval not to call shouldConcurrentCollect permanently	
        wait_on_cms_lock(CMSCheckInterval);	
      }	
    }	
    // Check if we should start a CMS collection cycle	
    if (_collector-&
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值