Hotspot 垃圾回收之CMSCollector(一) 源码解析

    目录

1、acquire_control_and_collect

2、do_compaction_work

3、do_mark_sweep_work

4、collect_in_background

5、VM_CMS_Operation

6、VM_CMS_Initial_Mark / VM_CMS_Final_Remark

7、shouldConcurrentCollect

8、总结


     根据上一篇《Hotspot 垃圾回收之ConcurrentMarkSweepGeneration(三) 源码解析》对ConcurrentMarkSweepGeneration主要方法的实现分析可知,老年代的垃圾回收相关细节被完全封装在CMSCollector中,调用入口就是ConcurrentMarkSweepThread调用的CMSCollector::collect_in_background和ConcurrentMarkSweepGeneration调用的CMSCollector::collect方法,从本篇开始就顺着这两个入口的对相关方法的调用顺序,逐步讲解CMSCollector的实现细节,其定义和构造方法已经在《Hotspot 垃圾回收之ConcurrentMarkSweepGeneration(一) 源码解析》中讲解过了,重点关注相关方法的实现。

1、acquire_control_and_collect

      acquire_control_and_collect就是CMSCollector::collect方法的核心实现了,首先会从执行后台GC的CMSThread中获取GC的执行权限,然后判断是否需要压缩老年代,根据是否压缩走不同的标记清理逻辑。其实现如下:

void CMSCollector::acquire_control_and_collect(bool full,
        bool clear_all_soft_refs) {
  //当前线程处于安全点上      
  assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");
  //当前线程是VMThread
  assert(!Thread::current()->is_ConcurrentGC_thread(),
         "shouldn't try to acquire control from self!");

  //校验VMThread已经获取了CMS Token
  assert(ConcurrentMarkSweepThread::vm_thread_has_cms_token(),
         "VM thread should have CMS token");
  //当前的垃圾回收状态
  CollectorState first_state = _collectorState;

  //_foregroundGCIsActive置为true表示前台GC已经激活了
  _foregroundGCIsActive = true;

  //临时暂停ICMS模式
  ICMSDisabler icms_disabler;

  //校验已经获取了锁
  assert_lock_strong(bitMapLock());
  assert(haveFreelistLocks(), "Must be holding free list locks");
  //释放锁等待后台GC让出GC执行权
  bitMapLock()->unlock();
  releaseFreelistLocks();
  {
    //获取锁CGC_lock
    MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
    if (_foregroundGCShouldWait) {
      //_foregroundGCShouldWait为true,表示后台GC正在进行
      assert(ConcurrentMarkSweepThread::cmst() != NULL,
             "CMS thread must be running");
      //释放VMThread占用的CMS Token
      ConcurrentMarkSweepThread::clear_CMS_flag(
        ConcurrentMarkSweepThread::CMS_vm_has_token);  // release token
      // 唤醒可能等待的CMS Thread继续执行
      CGC_lock->notify();
      assert(!ConcurrentMarkSweepThread::vm_thread_wants_cms_token(),
             "Possible deadlock");       
      while (_foregroundGCShouldWait) {
        //循环等待直到_foregroundGCShouldWait变为false,即后台GC交出了GC执行权
        CGC_lock->wait(Mutex::_no_safepoint_check_flag);
      }
      //重新获取CMS Token
      ConcurrentMarkSweepThread::set_CMS_flag(
        ConcurrentMarkSweepThread::CMS_vm_has_token);
    }
  }
  assert(ConcurrentMarkSweepThread::vm_thread_has_cms_token(),
         "VM thread should have CMS token");
  //重新获取锁       
  getFreelistLocks();
  bitMapLock()->lock_without_safepoint_check();
  if (TraceCMSState) {
    gclog_or_tty->print_cr("CMS foreground collector has asked for control "
      INTPTR_FORMAT " with first state %d", Thread::current(), first_state);
    gclog_or_tty->print_cr("    gets control with state %d", _collectorState);
  }

  //判断是否需要进行压缩,如果不需要是否需要标记清理
  bool should_compact    = false;
  bool should_start_over = false;
  decide_foreground_collection_type(clear_all_soft_refs,
    &should_compact, &should_start_over);

  
  if (first_state > Idling) {
    //如果当前GC状态不是空闲,则说明后台GC已经完成了部分GC步骤,打印被中断日志
    report_concurrent_mode_interruption();
  }

  set_did_compact(should_compact);
  if (should_compact) {
    //清空discovered References链表中的References实例,Mark-Sweep-Compact代码假定他们的referent都不是NULL且
    //References实例都是存活的
    ref_processor()->clean_up_discovered_references();

    if (first_state > Idling) {
      //保存当前堆内存和元空间的使用情况
      save_heap_summary();
    }
    //执行压缩并标记清理,底层核心实现是GenMarkSweep
    do_compaction_work(clear_all_soft_refs);

    DefNewGeneration* young_gen = _young_gen->as_DefNewGeneration();
    //获取eden区的最大容量
    size_t max_eden_size = young_gen->max_capacity() -
                           young_gen->to()->capacity() -
                           young_gen->from()->capacity();
    GenCollectedHeap* gch = GenCollectedHeap::heap();
    GCCause::Cause gc_cause = gch->gc_cause();
    size_policy()->check_gc_overhead_limit(_young_gen->used(),
                                           young_gen->eden()->used(),
                                           _cmsGen->max_capacity(),
                                           max_eden_size,
                                           full,
                                           gc_cause,
                                           gch->collector_policy());
  } else {
    //执行标记清理
    do_mark_sweep_work(clear_all_soft_refs, first_state,
      should_start_over);
  }
  //清空扩展的原因
  clear_expansion_cause();
  //_foregroundGCIsActive置为false
  _foregroundGCIsActive = false;
  return;
}

void CMSCollector::decide_foreground_collection_type(
  bool clear_all_soft_refs, bool* should_compact,
  bool* should_start_over) {
  GenCollectedHeap* gch = GenCollectedHeap::heap();
  assert(gch->collector_policy()->is_two_generation_policy(),
         "You may want to check the correctness of the following");
 
  if (gch->incremental_collection_will_fail(false /* don't consult_young */)) {
    //如果增量收集会失败
    assert(!_cmsGen->incremental_collection_failed(),
           "Should have been noticed, reacted to and cleared");
    _cmsGen->set_incremental_collection_failed();
  }
  //UseCMSCompactAtFullCollection表示在Full GC时是否执行压缩,默认为true
  //CMSFullGCsBeforeCompaction表示一个阈值,Full GC的次数超过该值才会执行压缩
  *should_compact =
    UseCMSCompactAtFullCollection &&
    ((_full_gcs_since_conc_gc >= CMSFullGCsBeforeCompaction) ||
     GCCause::is_user_requested_gc(gch->gc_cause()) || //用户通过System.gc方法请求GC
     gch->incremental_collection_will_fail(true /* consult_young */)); //增量收集失败
  *should_start_over = false;
  //如果should_compact为false且clear_all_soft_refs为true
  if (clear_all_soft_refs && !*should_compact) {
    //当clear_all_soft_refs为true时是否需要压缩,默认为true
    if (CMSCompactWhenClearAllSoftRefs) {
      *should_compact = true;
    } else {
      //如果当前GC已经过FinalMarking环节了,在该环节才处理所有的Refenrence,则需要重新开始一轮GC,
      //重新查找待处理的Refenrence
      if (_collectorState > FinalMarking) {
        //将GC的状态设置为重置
        _collectorState = Resetting; // skip to reset to start new cycle
        //执行重置
        reset(false /* == !asynch */);
        *should_start_over = true;
      } 
    }
  }
}

void CMSCollector::report_concurrent_mode_interruption() {
  if (is_external_interruption()) {
    if (PrintGCDetails) {
      gclog_or_tty->print(" (concurrent mode interrupted)");
    }
  } else {
    if (PrintGCDetails) {
      gclog_or_tty->print(" (concurrent mode failure)");
    }
    _gc_tracer_cm->report_concurrent_mode_failure();
  }
}

bool CMSCollector::is_external_interruption() {
  GCCause::Cause cause = GenCollectedHeap::heap()->gc_cause();
  return GCCause::is_user_requested_gc(cause) ||
         GCCause::is_serviceability_requested_gc(cause);
}

  inline static bool is_user_requested_gc(GCCause::Cause cause) {
    return (cause == GCCause::_java_lang_system_gc ||
            cause == GCCause::_jvmti_force_gc);
  }

  inline static bool is_serviceability_requested_gc(GCCause::Cause
                                                             cause) {
    return (cause == GCCause::_jvmti_force_gc ||
            cause == GCCause::_heap_inspection ||
            cause == GCCause::_heap_dump);
  }

void CMSCollector::save_heap_summary() {
  GenCollectedHeap* gch = GenCollectedHeap::heap();
  _last_heap_summary = gch->create_heap_summary();
  _last_metaspace_summary = gch->create_metaspace_summary();
}

 其调用链如下:

代码中用到的ICMSDisabler的定义如下:

 

2、do_compaction_work

     该方法是老年代需要压缩时执行msc_collection即Mark-Sweep-Compact collection的入口方法,核心逻辑都在GenMarkSweep::invoke_at_safepoint方法中,该方法就负责msc_collection开始前的通知和准备,结束后通知和状态重置工作,其实现如下:

void CMSCollector::do_compaction_work(bool clear_all_soft_refs) {
  GenCollectedHeap* gch = GenCollectedHeap::heap();

  //通知计时器和跟踪器 GC开始
  STWGCTimer* gc_timer = GenMarkSweep::gc_timer();
  gc_timer->register_gc_start();
  SerialOldTracer* gc_tracer = GenMarkSweep::gc_tracer();
  gc_tracer->report_gc_start(gch->gc_cause(), gc_timer->gc_start());

  GCTraceTime t("CMS:MSC ", PrintGCDetails && Verbose, true, NULL, gc_tracer->gc_id());
  if (PrintGC && Verbose && !(GCCause::is_user_requested_gc(gch->gc_cause()))) {
    gclog_or_tty->print_cr("Compact ConcurrentMarkSweepGeneration after %d "
      "collections passed to foreground collector", _full_gcs_since_conc_gc);
  }

  if (UseAdaptiveSizePolicy) {
    //msc就是Mark-Sweep-Compact的简写,通知CMSAdaptiveSizePolicy GC开始
    size_policy()->msc_col
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值