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

     目录

1、PushAndMarkClosure

2、SurvivorSpacePrecleanClosure

3、MarkRefsIntoAndScanClosure

4、ScanMarkedObjectsAgainCarefullyClosure

5、PrecleanKlassClosure

6、Precleaning 和 AbortablePreclean 总结

7、checkpointRootsFinal

8、do_remark_parallel / do_remark_non_parallel

9、refProcessingWork


本篇博客继续上一篇《Hotspot 垃圾回收之CMSCollector(三) 源码解析》讲解Precleaning和AbortablePreclean步骤依赖的相关Closure实现。

1、PushAndMarkClosure

      PushAndMarkClosure用于遍历survivor区的oop,其实现跟CMSKeepAliveClosure基本一致,如果该oop在BitMap未打标则打标,并将其放到_mark_stack中,如果_mark_stack满了且_concurrent_precleaning为false,则将其放到通过对象头指针构成的链表overflow_list中;如果_mark_stack满了且_concurrent_precleaning为true,则在_mod_union_table中打标,注意如果对象是数组,则数组的起止位置之间内存区域都需要在_mod_union_table中打标。其实现如下:

PushAndMarkClosure::PushAndMarkClosure(CMSCollector* collector,
                                       MemRegion span,
                                       ReferenceProcessor* rp,
                                       CMSBitMap* bit_map,
                                       CMSBitMap* mod_union_table,
                                       CMSMarkStack*  mark_stack,
                                       bool           concurrent_precleaning):
  MetadataAwareOopClosure(rp),
  _collector(collector),
  _span(span),
  _bit_map(bit_map),
  _mod_union_table(mod_union_table),
  _mark_stack(mark_stack),
  _concurrent_precleaning(concurrent_precleaning)
{
  assert(_ref_processor != NULL, "_ref_processor shouldn't be NULL");
}


void PushAndMarkClosure::do_oop(oop obj) {
  assert(obj->is_oop_or_null(true /* ignore mark word */),
         "expected an oop or NULL");
  HeapWord* addr = (HeapWord*)obj;
  if (_span.contains(addr) && !_bit_map->isMarked(addr)) {
    //如果BitMap未打标,则打标
    _bit_map->mark(addr);         // ... now grey
    bool simulate_overflow = false;
  
    if (simulate_overflow || !_mark_stack->push(obj)) {
      //如果_mark_stack满了,push失败了
      if (_concurrent_precleaning) {
         if (obj->is_objArray()) {
           size_t sz = obj->size();
           HeapWord* end_card_addr = (HeapWord*)round_to(
                                        (intptr_t)(addr+sz), CardTableModRefBS::card_size);
           MemRegion redirty_range = MemRegion(addr, end_card_addr);
           assert(!redirty_range.is_empty(), "Arithmetical tautology");
           _mod_union_table->mark_range(redirty_range);
         } else {
           _mod_union_table->mark(addr);
         }
         _collector->_ser_pmc_preclean_ovflw++;
      } else {
         //_concurrent_precleaning为false
         _collector->push_on_overflow_list(obj);
         _collector->_ser_pmc_remark_ovflw++;
      }
    }
  }
}

2、SurvivorSpacePrecleanClosure

      SurvivorSpacePrecleanClosure用来遍历survivor的from和to区中包含的对象,对每个对象遍历其所引用的其他对象,用PushAndMarkClosure来处理其他对象,PushAndMarkClosure会将其他对象放到_mark_stack中,然后SurvivorSpacePrecleanClosure再使用PushAndMarkClosure来处理_mark_stack中的对象,直到所引用的对象全部遍历完成,其实现如下:

  SurvivorSpacePrecleanClosure(CMSCollector* collector,
                               MemRegion     span,
                               CMSBitMap*    bit_map,
                               CMSMarkStack* mark_stack,
                               PushAndMarkClosure* cl,
                               unsigned int  before_count,
                               bool          should_yield):
    _collector(collector),
    _span(span),
    _yield(should_yield),
    _bit_map(bit_map),
    _mark_stack(mark_stack),
    _scanning_closure(cl),
    _before_count(before_count)
  { }

size_t SurvivorSpacePrecleanClosure::do_object_careful(oop p) {

  HeapWord* addr = (HeapWord*)p;
  //span是老年代的内存区域,所以肯定不包含survivor区的对象地址
  assert(!_span.contains(addr), "we are scanning the survivor spaces");
  //校验对象已初始化
  assert(p->klass_or_null() != NULL, "object should be initializd");
  assert(p->is_oop(true), "should be an oop");
  //遍历该对象所引用的其他对象,_scanning_closure处理其他对象时如果该对象未打标,会将其打标并加入到_mark_stack中
  size_t size = p->oop_iterate(_scanning_closure);
  //检查是否需要yeild,如果需要则执行yeild
  do_yield_check();
  //如果_mark_stack非空
  while (!_mark_stack->isEmpty()) {
    //弹出一个待处理的oop
    oop new_oop = _mark_stack->pop();
    assert(new_oop != NULL && new_oop->is_oop(), "Expected an oop");
    assert(_bit_map->isMarked((HeapWord*)new_oop),
           "only grey objects on this stack");
    //同样的方式遍历该oop所引用的其他oop
    new_oop->oop_iterate(_scanning_closure);
    //检查是否需要yeild,如果需要则执行yeild
    do_yield_check();
  }
  unsigned int after_count =
    GenCollectedHeap::heap()->total_collections();
  //如果should_abort_preclean为true
  bool abort = (_before_count != after_count) ||
               _collector->should_abort_preclean();
  return abort ? 0 : size;
}

inline void SurvivorSpacePrecleanClosure::do_yield_check() {
  if (ConcurrentMarkSweepThread::should_yield() &&
      !_collector->foregroundGCIsActive() &&
      _yield) {
    // Sample young gen size before and after yield
    _collector->sample_eden();
    do_yield_work();
    _collector->sample_eden();
  }
}

void SurvivorSpacePrecleanClosure::do_yield_work() {
  assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
         "CMS thread should hold CMS token");
  assert_lock_strong(_bit_map->lock());
  // Relinquish the bit map lock
  _bit_map->lock()->unlock();
  ConcurrentMarkSweepThread::desynchronize(true);
  ConcurrentMarkSweepThread::acknowledge_yield_request();
  _collector->stopTimer();
  GCPauseTimer p(_collector->size_policy()->concurrent_timer_ptr());
  if (PrintCMSStatistics != 0) {
    _collector->incrementYields();
  }
  _collector->icms_wait();

  // See the comment in coordinator_yield()
  for (unsigned i = 0; i < CMSYieldSleepCount &&
                       ConcurrentMarkSweepThread::should_yield() &&
                       !CMSCollector::foregroundGCIsActive(); ++i) {
    os::sleep(Thread::current(), 1, false);
    ConcurrentMarkSweepThread::acknowledge_yield_request();
  }

  ConcurrentMarkSweepThread::synchronize(true);
  _bit_map->lock()->lock_without_safepoint_check();
  _collector->startTimer();
}

3、MarkRefsIntoAndScanClosure

     MarkRefsIntoAndScanClosure的核心逻辑和SurvivorSpacePrecleanClosure基本相同,都是借助PushAndMarkClosure不断循环遍历,实现以某个oop为根节点,将该oop所引用的其他oop,其他oop所引用的其他oop全都遍历一遍,直到没有引用的oop了,其实现如下:

MarkRefsIntoAndScanClosure::MarkRefsIntoAndScanClosure(MemRegion span,
                                                       ReferenceProcessor* rp,
                                                       CMSBitMap* bit_map,
                                                       CMSBitMap* mod_union_table,
                                                       CMSMarkStack*  mark_stack,
                                                       CMSCollector* collector,
                                                       bool should_yield,
                                                       bool concurrent_precleaning):
  _collector(collector),
  _span(span),
  _bit_map(bit_map),
  _mark_stack(mark_stack),
  _pushAndMarkClosure(collector, span, rp, bit_map, mod_union_table,
                      mark_stack, concurrent_precleaning), //该属性就是PushAndMarkClosure
  _yield(should_yield),
  _concurrent_precleaning(concurrent_precleaning),
  _freelistLock(NULL)
{
  _ref_processor = rp;
  assert(_ref_processor != NULL, "_ref_processor shouldn't be NULL");
}

void MarkRefsIntoAndScanClosure::do_oop(oop obj) {
  if (obj != NULL) {
    assert(obj->is_oop(), "expected an oop");
    HeapWord* addr = (HeapWord*)obj;
    assert(_mark_stack->isEmpty(), "pre-condition (eager drainage)");
    assert(_collector->overflow_list_is_empty(),
           "overflow list should be empty");
    if (_span.contains(addr) &&
        !_bit_map->isMarked(addr)) {
      //如果该对象未打标,则在bitMap中打标
      _bit_map->mark(addr);
      //将该对象放入_mark_stack
      bool res = _mark_stack->push(obj);
      assert(res, "Should have space to push on empty stack");
      do {
        oop new_oop = _mark_stack->pop();
        assert(new_oop != NULL && new_oop->is_oop(), "Expected an oop");
        assert(_bit_map->isMarked((HeapWord*)new_oop),
               "only grey objects on this stack");
        //使用_pushAndMarkClosure遍历该对象所引用的其他oop,_pushAndMarkClosure会遍历其他oop中的每个oop所引用的
        //其他oop,把他们添加到_mark_stack中
        new_oop->oop_iterate(&_pushAndMarkClosure);
        //检查是否需要yield,如果需要则执行yield动作
        do_yield_check();
      } while (!_mark_stack->isEmpty() || //_mark_stack为空
               (!_concurrent_precleaning && take_from_overflow_list())); //overflow_list为空,两者都满足时终止循环
    }
    assert(_mark_stack->isEmpty(), "post-condition (eager drainage)");
    assert(_collector->overflow_list_is_empty(),
           "overflow list was drained above");
    //CMSOverflowEarlyRestoration为false,表示是否较早的恢复_preserved_oop_stack中保存的oop的对象头
    if (!_concurrent_precleaning && CMSOverflowEarlyRestoration) {
      _collector->restore_preserved_marks_if_any();
      assert(_collector->no_preserved_marks(), "No preserved marks");
    }
    assert(!CMSOverflowEarlyRestoration || _collector->no_preserved_marks(),
           "All preserved marks should have been restored above");
  }
}

inline void MarkRefsIntoAndScanClosure::do_yield_check() {
  if (_yield &&
      !_collector->foregroundGCIsActive() &&
      ConcurrentMarkSweepThread::should_yield()) {
    do_yield_work();
  }
}

void MarkRefsIntoAndScanClosure::do_yield_work() {
  assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
         "CMS thread should hold CMS token");
  assert_lock_strong(_freelistLock);
  assert_lock_strong(_bit_map->lock());
  // relinquish the free_list_lock and bitMaplock()
  _bit_map->lock()->unlock();
  _freelistLock->unlock();
  ConcurrentMarkSweepThread::desynchronize(true);
  ConcurrentMarkSweepThread::acknowledge_yield_request();
  _collector->stopTimer();
  GCPauseTimer p(_collector->size_policy()->concurrent_timer_ptr());
  if (PrintCMSStatistics != 0) {
    _collector->incrementYields();
  }
  _collector->icms_wait();

  // See the comment in coordinator_yield()
  for (unsigned i = 0;
       i < CMSYieldSleepCount &&
       ConcurrentMarkSweepThread::should_yield() &&
       !CMSCollector::foregroundGCIsActive();
       ++i) {
    os::sleep(Thread::current(), 1, false);
    ConcurrentMarkSweepThread::acknowledge_yield_request();
  }

  ConcurrentMarkSweepThread::synchronize(true);
  _freelistLock->lock_without_safepoint_check();
  _bit_map->lock()->lock_without_safepoint_check();
  _collector->startTimer();
}

bool MarkRefsIntoAndScanClosure::take_from_overflow_list() {
  size_t num = MIN2((size_t)(_mark_stack->capacity() - _mark_stack->length())/4,
                    (size_t)ParGCDesiredObjsFromOverflowList);
  //从overflow_list中取出最多num个待处理oop放入_mark_stack中
  bool res = _collector->take_from_overflow_list(num, _mark_stack);
  assert(_collector->overflow_list_is_empty() || res,
         "If list is not empty, we should have taken something");
  assert(!res || !_mark_stack->isEmpty(),
         "If we took something, it should now be on our stack");
  return res;
}

void CMSCollector::restore_preserved_marks_if_any() {
  //校验在安全点上
  assert(SafepointSynchronize::is_at_safepoint(),
         "world should be stopped");
  assert(Thread::current()->is_ConcurrentGC_thread() ||
         Thread::current()->is_VM_thread(),
         "should be single-threaded");
  assert(_preserved_oop_stack.size() == _preserved_mark_stack.size(),
         "bijection");

  while (!_preserved_oop_stack.is_empty()) {
    //弹出oop
    oop p = _preserved_oop_stack.pop();
    assert(p->is_oop(), "Should be an oop");
    assert(_span.contains(p), "oop should be in _span");
    assert(p->mark() == markOopDesc::prototype(),
           "Set when taken from overflow list");
    //弹出对应的对象头
    markOop m = _preserved_mark_stack.pop();
    //恢复原来的对象头
    p->set_mark(m);
  }
  assert(_preserved_mark_stack.is_empty() && _preserved_oop_stack.is_empty(),
         "stacks were cleared above");
}

#ifndef PRODUCT
bool CMSCollector::no_preserved_marks() const {
  return _preserved_mark_stack.is_empty() && _preserved_oop_stack.is_empty();
}
#endif

4、ScanMarkedObjectsAgainCarefullyClosure

      ScanMarkedObjectsAgainCarefullyClosure用来遍历从_modUnionTable或者卡表(CardTableModRefBS)中找到的脏的卡表项对应的内存区域中包含的对象,如果该对象已打标且完成初始化,则用MarkRefsIntoAndScanClosure遍历该对象所引用的其他对象,否则的话跳过该对象,是preclean_mod_union_table和preclean_card_table中使用的遍历方法,注意该方法返回0的时候调用方会负责终止遍历,并返回当前已遍历区域的终止地址。其实现如下:

  ScanMarkedObjectsAgainCarefullyClosure(CMSCollector* collector,
                                         MemRegion     span,
                                         CMSBitMap* bitMap,
                                         CMSMarkStack*  markStack,
                                         MarkRefsIntoAndScanClosure* cl,
                                         bool should_yield):
    _collector(collector),
    _span(span),
    _yield(should_yield),
    _bitMap(bitMap),
    _markStack(markStack),
    _scanningClosure(cl) {
  }

size_t ScanMarkedObjectsAgainCarefullyClosure::do_object_careful_m(
  oop p, MemRegion mr) {

  size_t size = 0;
  HeapWord* addr = (HeapWord*)p;
  DEBUG_ONLY(_collector->verify_work_stacks_empty();)
  assert(_span.contains(addr), "we are scanning the CMS generation");
  // check if it's time to yield
  if (do_yield_check()) {
    //如果需要yield则执行yeild,yeild结束后should_abort_preclean返回true则终止执行
    return 0;
  }
  if (_bitMap->isMarked(addr)) {
    //addr已打标
    if (p->klass_or_null() != NULL) {
        //该oop已初始化
        assert(p->is_oop(true), "should be an oop");
        if (p->is_objArray()) {
          //用MarkRefsIntoAndScanClosure来遍历该数组所引用的其他对象,遍历完成返回数组大小
          size = CompactibleFreeListSpace::adjustObjectSize(
                   p->oop_iterate(_scanningClosure, mr));
        } else {
          //用MarkRefsIntoAndScanClosure来遍历该对象所引用的其他对象,遍历完成返回对象大小
          size = CompactibleFreeListSpace::adjustObjectSize(
                   p->oop_iterate(_scanningClosure));
        }
        
    } else {
      //该oop未初始化
      assert(_bitMap->isMarked(addr+1), "missing Printezis mark?");
      //获取addr + 2之后的一个被打标的位,即该对象的结束地址,然后根据结束地址计算对象大小
      HeapWord* nextOneAddr = _bitMap->getNextMarkedWordAddress(addr + 2);
      size = pointer_delta(nextOneAddr + 1, addr);
      assert(size == CompactibleFreeListSpace::adjustObjectSize(size),
             "alignment problem");
    }
  } else {
    //addr未打标
    if (p->klass_or_null() == NULL) {
      //klass为NULL,未初始化的对象
      assert(size == 0, "Initial value");
    } else {
      //klass不为NULL,根据klass获取对象大小
      assert(p->is_oop(true), "should be an oop");
      size = CompactibleFreeListSpace::adjustObjectSize(p->size());
    }
  }
  return size;
}

inline bool ScanMarkedObjectsAgainCarefullyClosure::do_yield_check() {
  if (ConcurrentMarkSweepThread::should_yield() &&
      !_collector->foregroundGCIsActive() &&
      _yield) {
    // Sample young gen size before and after yield
    _collector->sample_eden();
    do_yield_work();
    _collector->sample_eden();
    return _collector->should_abort_preclean();
  }
  return false;
}

void ScanMarkedObjectsAgainCarefullyClosure::do_yield_work() {
  assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
         "CMS thread should hold CMS token");
  assert_lock_strong(_freelistLock);
  assert_lock_strong(_bitMap->lock());
  // relinquish the free_list_lock and bitMaplock()
  _bitMap->lock()->unlock();
  _freelistLock->unlock();
  ConcurrentMarkSweepThread::desynchronize(true);
  ConcurrentMarkSweepThread::acknowledge_yield_request();
  _collector->stopTimer();
  GCPauseTimer p(_collector->size_policy()->concurrent_timer_ptr());
  if (PrintCMSStatistics != 0) {
    _collector->incrementYields();
  }
  _collector->icms_wait();

  // See the comment in coordinator_yield()
  for (unsigned i = 0; i < CMSYieldSleepCount &&
                   ConcurrentMarkSweepThread::should_yield() &&
                   !CMSCollector::foregroundGCIsActive(); ++i) {
    os::sleep(Thread::current(), 1, false);
    ConcurrentMarkSweepThread::acknowledge_yield_request();
  }

  ConcurrentMarkSweepThread::synchronize(true);
  _freelistLock->lock_without_safepoint_check();
  _bitMap->lock()->lock_without_safepoint_check();
  _collector->startTimer();
}

5、PrecleanKlassClosure

     PrecleanKlassClosure是preclean_klasses使用的,使用MarkRefsIntoAndScanClosure来遍历发生修改的klass对应的类Class实例,其实现如下:

class PrecleanKlassClosure : public KlassClosure {
  KlassToOopClosure _cm_klass_closure;
 public:
  PrecleanKlassClosure(OopClosure* oop_closure) : _cm_klass_closure(oop_closure) {}
  void do_klass(Klass* k) {
    if (k->has_accumulated_modified_oops()) {
      k->clear_accumulated_modified_oops();

      _cm_klass_closure.do_klass(k);
    }
  }
};

void KlassToOopClosure::do_klass(Klass* k) {
  assert(_oop_closure != NULL, "Not initialized?");
  k->oops_do(_oop_closure);
}

void Klass::oops_do(OopClosure* cl) {
  cl->do_oop(&_java_mirror);
}

6、Precleaning 和 AbortablePreclean 总结

      Precleaning和AbortablePreclean两步都是后台GC才有的,不要求JVM处于安全点上,其底层核心都是同一个方法preclean_work,注意只有当CMSPrecleaningEnabled参数为true时,后台GC才会由Precleaning流转到AbortablePreclean状态,否则直接进入到FinalMarking状态,该参数默认为true。Precleaning时只执行一遍preclean_work,并且preclean_work会清理查找到的Reference实例;AbortablePreclean会执行多次preclean_work,并且preclean_work会遍历survivor区中的对象,当达到某个条件时才退出。preclean_work会根据入参决定是否清理Reference实例和遍历survivor区中的对象,该方法主要遍历从_modUnionTable或者卡表(CardTableModRefBS)中找到的脏的卡表项对应的内存区域中包含的已打标对象,以这些对象为根节点不断遍历其所引用的其他对象,将其在BitMap中打标;除此之外,还遍历脏的klass对应的类Class实例所引用的对象。

    这两个步骤涉及两个重要属性,_start_sampling和_abort_preclean,前者表示是否需要采集eden区的top地址,后者表示是否需要终止preclean,两者在CMSCollector初始化时都是为false。_start_sampling在preclean方法中根据eden区的内存使用率决定,默认配置下只有使用率低于10%的时候才会将_start_sampling置为true,否则为false。_abort_preclean只在sample_eden方法中修改,在_start_sampling为true且eden区内存使用率大于50%时才置为true,如果_start_sampling为false,则sample_eden方法直接返回,即这种情形下_abort_preclean始终为false。读取_abort_preclean属性的只有一个方法should_abort_preclean,其实现如下:

该方法的调用链如下:

 

其中如果should_abort_preclean方法返回true,ScanMarkedObjectsAgainCarefullyClosure会中止遍历返回0,然后preclean_card_table和preclean_mod_union_table都会终止遍历,最外层的abortable_preclean也会终止preclean_work循环,将状态置为FinalMarking。

7、checkpointRootsFinal

     checkpointRootsFinal负责完成处理步骤FinalMarking,如果前台GC执行了InitialMarking则该步骤不会执行遍历标记,因为这就表示由VMThead完整的执行整个GC过程,执行期间会stop the world,引用关系不会发生改变;如果是后台GC执行的该方法或者后台GC执行InitialMarking,后面交给前台GC执行FinalMarking都会重新执行遍历标记,因为在InitialMarking和FinalMarking期间引用关系可能发生改变,需要重新标记。除按需重新标记外,checkpointRootsFinal还负责清理Reference实例,将留下的Reference实例放到Reference的pend list中;还负责执行类卸载相关的工作,如清理klass,符号表,字符串表,CodeCache中保存的本地代码等。

void CMSCollector::checkpointRootsFinal(bool asynch,
  bool clear_all_soft_refs, bool init_mark_was_synchronous) {
  assert(_collectorState == FinalMarking, "incorrect state transition?");
  check_correct_thread_executing();
  // world is stopped at this checkpoint
  assert(SafepointSynchronize::is_at_safepoint(),
         "world should be stopped");
  TraceCMSMemoryManagerStats tms(_collectorState,GenCollectedHeap::heap()->gc_cause());

  verify_work_stacks_empty();
  verify_overflow_empty();

  SpecializationStats::clear();
  if (PrintGCDetails) {
    gclog_or_tty->print("[YG occupancy: " SIZE_FORMAT " K (" SIZE_FORMAT " K)]",
                        _young_gen->used() / K,
                        _young_gen->capacity() / K);
  }
  if (asynch) {
    //异步GC
    //CMSScavengeBeforeRemark表示是否尝试在remark前扫描一遍年轻代,默认为false
    if (CMSScavengeBeforeRemark) {
      GenCollectedHeap* gch = GenCollectedHeap::heap();
      //gch->do_collection希望_is_gc_active为false
      FlagSetting fl(gch->_is_gc_active, false);
      int level = _cmsGen->level() - 1;
      if (level >= 0) {
        //这里实际是清理年轻代
        gch->do_collection(true,        // full (i.e. force, see below)
                           false,       // !clear_all_soft_refs
                           0,           // size
                           false,       // is_tlab
                           level        // max_level
                          );
      }
    }
    //获取FreelistLock和bitMapLock
    FreelistLocker x(this);
    MutexLockerEx y(bitMapLock(),
                    Mutex::_no_safepoint_check_flag);
    assert(!init_mark_was_synchronous, "but that's impossible!");
    checkpointRootsFinalWork(asynch, clear_all_soft_refs, false);
  } else {
    //同步GC
    checkpointRootsFinalWork(asynch, clear_all_soft_refs,
                             init_mark_was_synchronous);
  }
  verify_work_stacks_empty();
  verify_overflow_empty();
  SpecializationStats::print();
}

void CMSCollector::checkpointRootsFinalWork(bool asynch,
  bool clear_all_soft_refs, bool init_mark_was_synchronous) {
  //校验获取了锁
  assert(haveFreelistLocks(), "must have free list locks");
  assert_lock_strong(bitMapLock());

  if (UseAdaptiveSizePolicy) {
    //通知checkpoint_roots_final步骤开始
    size_policy()->checkpoint_roots_final_begin();
  }

  ResourceMark rm;
  HandleMark   hm;

  GenCollectedHeap* gch = GenCollectedHeap::heap();

  if (should_unload_classes()) {
    //如果需要卸载类,则执行CodeCache的GC预处理
    CodeCache::gc_prologue();
  }
  assert(haveFreelistLocks(), "must have free list locks");
  assert_lock_strong(bitMapLock());

  if (!init_mark_was_synchronous) {
     //init_mark_was_synchronous为false
    //确保TLAB不会被释放掉
    gch->ensure_parsability(false);  // fill TLAB's, but no need to retire them
    //保存各代的save_mark
    gch->save_marks();

    if (CMSPrintEdenSurvivorChunks) {
      print_eden_and_survivor_chunk_arrays();
    }

    {
      COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;)

      //CMSParallelRemarkEnabled默认是为true,表示是否并行执行Remark
      if (CMSParallelRemarkEnabled && CollectedHeap::use_parallel_gc_threads()) {
        GCTraceTime t("Rescan (parallel) ", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
        do_remark_parallel();
      } else {
        GCTraceTime t("Rescan (non-parallel) ", PrintGCDetails, false,
                    _gc_timer_cm, _gc_tracer_cm->gc_id());
        do_remark_non_parallel();
      }
    }
  } else {
    //init_mark_was_synchronous为true,表示执行InitialMarking是同步的,会stop the word
    //如果是同步GC执行的InitialMarking,则init_mark_was_synchronous为true,同步GC的整个过程都会stop the world
    //如果是异步GC执行的InitialMarking,或者是异步GC执行checkpointRootsFinal方法,则init_mark_was_synchronous为false
    assert(!asynch, "Can't have init_mark_was_synchronous in asynch mode");
  }
  verify_work_stacks_empty();
  verify_overflow_empty();

  {
    //处理查找的Reference实例,执行Klass卸载,符号表,字符串表,CodeCache清理,最后将剩余的Reference实例放入Reference类的pending_list中
    refProcessingWork(asynch, clear_all_soft_refs);
  }
  verify_work_stacks_empty();
  verify_overflow_empty();

  if (should_unload_classes()) {
    //执行CodeCache的gc后处理
    CodeCache::gc_epilogue();
  }
  JvmtiExport::gc_epilogue();
  
  assert(_markStack.isEmpty(), "No grey objects");
  size_t ser_ovflw = _ser_pmc_remark_ovflw + _ser_pmc_preclean_ovflw +
                     _ser_kac_ovflw        + _ser_kac_preclean_ovflw;
  if (ser_ovflw > 0) {
    if (PrintCMSStatistics != 0) {
      gclog_or_tty->print_cr("Marking stack overflow (benign) "
        "(pmc_pc=" SIZE_FORMAT ", pmc_rm=" SIZE_FORMAT ", kac=" SIZE_FORMAT
        ", kac_preclean=" SIZE_FORMAT ")",
        _ser_pmc_preclean_ovflw, _ser_pmc_remark_ovflw,
        _ser_kac_ovflw, _ser_kac_preclean_ovflw);
    }
    //_markStack扩容
    _markStack.expand();
    //计数置0
    _ser_pmc_remark_ovflw = 0;
    _ser_pmc_preclean_ovflw = 0;
    _ser_kac_preclean_ovflw = 0;
    _ser_kac_ovflw = 0;
  }
  if (_par_pmc_remark_ovflw > 0 || _par_kac_ovflw > 0) {
    if (PrintCMSStatistics != 0) {
      gclog_or_tty->print_cr("Work queue overflow (benign) "
        "(pmc_rm=" SIZE_FORMAT ", kac=" SIZE_FORMAT ")",
        _par_pmc_remark_ovflw, _par_kac_ovflw);
    }
     //计数置0
    _par_pmc_remark_ovflw = 0;
    _par_kac_ovflw = 0;
  }
  if (PrintCMSStatistics != 0) {
     if (_markStack._hit_limit > 0) {
       gclog_or_tty->print_cr(" (benign) Hit max stack size limit (" SIZE_FORMAT ")",
                              _markStack._hit_limit);
     }
     if (_markStack._failed_double > 0) {
       gclog_or_tty->print_cr(" (benign) Failed stack doubling (" SIZE_FORMAT "),"
                              " current capacity " SIZE_FORMAT,
                              _markStack._failed_double,
                              _markStack.capacity());
     }
  }
 //计数置0
  _markStack._hit_limit = 0;
  _markStack._failed_double = 0;

  if ((VerifyAfterGC || VerifyDuringGC) &&
      GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
    verify_after_remark();
  }

  _gc_tracer_cm->report_object_count_after_gc(&_is_alive_closure);

  //修改状态
  _collectorState = Sweeping;
  // Call isAllClear() under bitMapLock
  assert(_modUnionTable.isAllClear(),
      "Should be clear by end of the final marking");
  assert(_ct->klass_rem_set()->mod_union_is_clear(),
      "Should be clear by end of the final marking");
  if (UseAdaptiveSizePolicy) {
    //通知checkpoint_roots_final操作结束
    size_policy()->checkpoint_roots_final_end(gch->gc_cause());
  }
}

8、do_remark_parallel / do_remark_non_parallel

     这两个方法就是checkpointRootsFinal中执行并行和串行标记清理的实现方法,前者的核心逻辑封装在CMSParRemarkTask中,后者的核心逻辑封装在各Closure中,其实现如下:

void CMSCollector::do_remark_parallel() {
  GenCollectedHeap* gch = GenCollectedHeap::heap();
  FlexibleWorkGang* workers = gch->workers();
  assert(workers != NULL, "Need parallel worker threads.");
  //设置并行的GC线程数
  int n_workers = workers->active_workers();
  if (n_workers == 0) {
    assert(n_workers > 0, "Should have been set during scavenge");
    n_workers = ParallelGCThreads;
    workers->set_active_workers(n_workers);
  }
  CompactibleFreeListSpace* cms_space  = _cmsGen->cmsSpace();

  CMSParRemarkTask tsk(this,
    cms_space,
    n_workers, workers, task_queues());

  // Set up for parallel process_roots work.
  gch->set_par_threads(n_workers);
  //初始化年轻代三个区的SequentialSubTasksDone
  initialize_sequential_subtasks_for_young_gen_rescan(n_workers);

  //初始化老年代的SequentialSubTasksDone
  cms_space->initialize_sequential_subtasks_for_rescan(n_workers);

  if (n_workers > 1) {
    //临时设置discovery_is_mt属性为true
    ReferenceProcessorMTDiscoveryMutator mt(ref_processor(), true);
    GenCollectedHeap::StrongRootsScope srs(gch);
    //执行任务
    workers->run_task(&tsk);
  } else {
    //临时设置discovery_is_mt属性为false
    ReferenceProcessorMTDiscoveryMutator mt(ref_processor(), false);
    GenCollectedHeap::StrongRootsScope srs(gch);
    tsk.work(0);
  }

  gch->set_par_threads(0);  // 0 ==> non-parallel.
  //恢复_preserved_oop_stack中保存的oop的对象头
  restore_preserved_marks_if_any();
}

void
CompactibleFreeListSpace::
initialize_sequential_subtasks_for_rescan(int n_threads) {
  // The "size" of each task is fixed according to rescan_task_size.
  assert(n_threads > 0, "Unexpected n_threads argument");
  const size_t task_size = rescan_task_size();
  //根据rescan_task_size和已使用内存,计算需要的任务数
  size_t n_tasks = (used_region().word_size() + task_size - 1)/task_size;
  assert((n_tasks == 0) == used_region().is_empty(), "n_tasks incorrect");
  assert(n_tasks == 0 ||
         ((used_region().start() + (n_tasks - 1)*task_size < used_region().end()) &&
          (used_region().start() + n_tasks*task_size >= used_region().end())),
         "n_tasks calculation incorrect");
  SequentialSubTasksDone* pst = conc_par_seq_tasks();
  assert(!pst->valid(), "Clobbering existing data?");
  //设置所需的线程数和任务数
  pst->set_n_threads(n_threads);
  pst->set_n_tasks((int)n_tasks);
}

const size_t rescan_task_size()  const { return _rescan_task_size;  }

void CMSCollector::do_remark_non_parallel() {
  ResourceMark rm;
  HandleMark   hm;
  GenCollectedHeap* gch = GenCollectedHeap::heap();
   //临时设置discovery_is_mt属性为false
  ReferenceProcessorMTDiscoveryMutator mt(ref_processor(), false);

  MarkRefsIntoAndScanClosure
    mrias_cl(_span, ref_processor(), &_markBitMap, NULL /* not precleaning */,
             &_markStack, this,
             false /* should_yield */, false /* not precleaning */);
  MarkFromDirtyCardsClosure
    markFromDirtyCardsClosure(this, _span,
                              NULL,  // space is set further below
                              &_markBitMap, &_markStack, &mrias_cl);
  {
    GCTraceTime t("grey object rescan", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
    {
      ModUnionClosure modUnionClosure(&_modUnionTable);
      //遍历卡表,将脏的卡表项对应的地址在mod union table中打标
      _ct->ct_bs()->dirty_card_iterate(
                      _cmsGen->used_region(),
                      &modUnionClosure);
    }
  
    const int alignment =
      CardTableModRefBS::card_size * BitsPerWord;
    {
      // ... First handle dirty cards in CMS gen
      markFromDirtyCardsClosure.set_space(_cmsGen->cmsSpace());
      MemRegion ur = _cmsGen->used_region();
      HeapWord* lb = ur.start();
      HeapWord* ub = (HeapWord*)round_to((intptr_t)ur.end(), alignment);
      MemRegion cms_span(lb, ub);
      //遍历_modUnionTable中被打标的位,即脏的卡表项对应的内存区域中的对象,以他们为根对象遍历所有引用的对象,将其在BitMap中打标
      _modUnionTable.dirty_range_iterate_clear(cms_span,
                                               &markFromDirtyCardsClosure);
      verify_work_stacks_empty();
      if (PrintCMSStatistics != 0) {
        gclog_or_tty->print(" (re-scanned " SIZE_FORMAT " dirty cards in cms gen) ",
          markFromDirtyCardsClosure.num_dirty_cards());
      }
    }
  }
  if (VerifyDuringGC &&
      GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
    HandleMark hm;  // Discard invalid handles created during verification
    Universe::verify();
  }
  {
    GCTraceTime t("root rescan", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());

    verify_work_stacks_empty();

    gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
    GenCollectedHeap::StrongRootsScope srs(gch);
    //以年轻代的对象作为根节点遍历老年代
    gch->gen_process_roots(_cmsGen->level(),
                           true,  // younger gens as roots
                           false, // use the local StrongRootsScope
                           GenCollectedHeap::ScanningOption(roots_scanning_options()),
                           should_unload_classes(),
                           &mrias_cl,
                           NULL,
                           NULL); // The dirty klasses will be handled below

    assert(should_unload_classes()
           || (roots_scanning_options() & GenCollectedHeap::SO_AllCodeCache),
           "if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops");
  }

  {
    GCTraceTime t("visit unhandled CLDs", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());

    verify_work_stacks_empty();

    //遍历新创建的ClassLoaderData
    ResourceMark rm;
    GrowableArray<ClassLoaderData*>* array = ClassLoaderDataGraph::new_clds();
    for (int i = 0; i < array->length(); i++) {
      mrias_cl.do_class_loader_data(array->at(i));
    }

    // We don't need to keep track of new CLDs anymore.
    ClassLoaderDataGraph::remember_new_clds(false);

    verify_work_stacks_empty();
  }

  {
    GCTraceTime t("dirty klass scan", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());

    verify_work_stacks_empty();

    RemarkKlassClosure remark_klass_closure(&mrias_cl);
    //遍历所有发生修改的Klass
    ClassLoaderDataGraph::classes_do(&remark_klass_closure);

    verify_work_stacks_empty();
  }

  verify_work_stacks_empty();
  // Restore evacuated mark words, if any, used for overflow list links
  if (!CMSOverflowEarlyRestoration) {
    restore_preserved_marks_if_any();
  }
  verify_overflow_empty();
}

9、refProcessingWork

     该方法就是checkpointRootsFinal中负责清理Reference实例的方法,如果_should_unload_classes为true,即需要卸载类的时候,还要清理SystemDictionary,CodeCache,SymbolTable,StringTable以及不再使用的Klass。

void CMSCollector::refProcessingWork(bool asynch, bool clear_all_soft_refs) {

  ResourceMark rm;
  HandleMark   hm;

  ReferenceProcessor* rp = ref_processor();
  assert(rp->span().equals(_span), "Spans should be equal");
  assert(!rp->enqueuing_is_done(), "Enqueuing should not be complete");
  // Process weak references.
  rp->setup_policy(clear_all_soft_refs);
  verify_work_stacks_empty();

  CMSKeepAliveClosure cmsKeepAliveClosure(this, _span, &_markBitMap,
                                          &_markStack, false /* !preclean */);
  CMSDrainMarkingStackClosure cmsDrainMarkingStackClosure(this,
                                _span, &_markBitMap, &_markStack,
                                &cmsKeepAliveClosure, false /* !preclean */);
  {
    GCTraceTime t("weak refs processing", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());

    ReferenceProcessorStats stats;
    if (rp->processing_is_mt()) {
      GenCollectedHeap* gch = GenCollectedHeap::heap();
      //获取并行执行的线程数
      int active_workers = ParallelGCThreads;
      FlexibleWorkGang* workers = gch->workers();
      if (workers != NULL) {
        active_workers = workers->active_workers();
        assert(active_workers > 0, "Should have been set during scavenge");
      }
      rp->set_active_mt_degree(active_workers);
      //初始化执行并行清理的执行器
      CMSRefProcTaskExecutor task_executor(*this);
      //处理所有找到的Reference实例
      stats = rp->process_discovered_references(&_is_alive_closure,
                                        &cmsKeepAliveClosure,
                                        &cmsDrainMarkingStackClosure,
                                        &task_executor,
                                        _gc_timer_cm,
                                        _gc_tracer_cm->gc_id());
    } else {
      stats = rp->process_discovered_references(&_is_alive_closure,
                                        &cmsKeepAliveClosure,
                                        &cmsDrainMarkingStackClosure,
                                        NULL,
                                        _gc_timer_cm,
                                        _gc_tracer_cm->gc_id());
    }
    _gc_tracer_cm->report_gc_reference_stats(stats);

  }

  // This is the point where the entire marking should have completed.
  verify_work_stacks_empty();

  if (should_unload_classes()) {
    {
      //如果需要卸载类
      GCTraceTime t("class unloading", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());

      //清理SystemDictionary
      bool purged_class = SystemDictionary::do_unloading(&_is_alive_closure);

      //清理CodeCache
      CodeCache::do_unloading(&_is_alive_closure, purged_class);

      //清理不再使用的klass
      Klass::clean_weak_klass_links(&_is_alive_closure);
    }

    {
      GCTraceTime t("scrub symbol table", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
      //清理不再使用的符号引用
      SymbolTable::unlink();
    }

    {
      GCTraceTime t("scrub string table", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
      //清理不再使用的字符串
      StringTable::unlink(&_is_alive_closure);
    }
  }


  //恢复_preserved_oop_stack中保存的oop的对象头
  restore_preserved_marks_if_any();  // done single-threaded for now

  rp->set_enqueuing_is_done(true);
  //将剩余的Reference实例放入到Reference的pending_list中
  if (rp->processing_is_mt()) {
    rp->balance_all_queues();
    CMSRefProcTaskExecutor task_executor(*this);
    rp->enqueue_discovered_references(&task_executor);
  } else {
    rp->enqueue_discovered_references(NULL);
  }
  rp->verify_no_references_recorded();
  assert(!rp->discovery_enabled(), "should have been disabled");
}
发布了117 篇原创文章 · 获赞 8 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_31865983/article/details/104210298
今日推荐