js css html

CMS算法实现 -3

2023-01-28  本文已影响0人  程序员札记

总结下老年代GC各个步骤的主要处理流程。

1、InitialMarking / checkpointRootsInitialWork
其主要处理流程如下:

image.png

补充说明如下:

2、Marking / markFromRootsWork
其主要处理流程如下:

image.png

补充说明如下:

inline void MarkFromRootsClosure::do_yield_check() {
  //业务线程分配对象时会请求CMS Thread执行yeild,should_yield返回true
  //foregroundGCIsActive为true,表示前台GC已激活,此时后台GC应该尽快终止GC,将剩余处理步骤交接给前台GC处理
  //yeild是类属性,其值为CMSYield && asynch,CMSYield 默认为true,表示允许yeild,asynch表示后台GC,即如果是前台GC执行或者前台GC激活了则if不成立
  if (ConcurrentMarkSweepThread::should_yield() &&
      !_collector->foregroundGCIsActive() &&
      _yield) {
    //执行yeild
    do_yield_work();
  }
}
 
void MarkFromRootsClosure::do_yield_work() {
  //进入此方法只能是CMS Thread,必须持有CMS Token
  assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
         "CMS thread should hold CMS token");
  //释放锁
  assert_lock_strong(_bitMap->lock());
  _bitMap->lock()->unlock();
  ConcurrentMarkSweepThread::desynchronize(true);
  //将需要yeild的计数减1
  ConcurrentMarkSweepThread::acknowledge_yield_request();
  _collector->stopTimer();
  GCPauseTimer p(_collector->size_policy()->concurrent_timer_ptr());
  if (PrintCMSStatistics != 0) {
    _collector->incrementYields();
  }
  //icms增量收集模式使用,默认不开启
  _collector->icms_wait();
 
  // See the comment in coordinator_yield()
  for (unsigned i = 0; i < CMSYieldSleepCount &&
                       ConcurrentMarkSweepThread::should_yield() &&
                       !CMSCollector::foregroundGCIsActive(); ++i) {
    //循环休眠1ms
    os::sleep(Thread::current(), 1, false);
    ConcurrentMarkSweepThread::acknowledge_yield_request();
  }
  
 //重新获取锁
  ConcurrentMarkSweepThread::synchronize(true);
  _bitMap->lock()->lock_without_safepoint_check();
  _collector->startTimer();
}

3、Precleaning / AbortablePreclean / preclean_work
Precleaning和AbortablePreclean的底层实现都是preclean_work,前者只调用了一次,预清理Reference实例,后者是循环调用了多次,每次都清理survivor区的对象,preclean_work的主要处理流程如下:

image.png

补充说明如下:

image.png

补充说明如下:

5、Sweeping / sweepWork
其主要处理流程如下:


image.png

补充说明如下:

image.png

6、Resetting / reset
reset实际只干一件事,将markBitMap清空,如果是后台GC则分段清空,每清空一个内存段就需要检查是否需要yeild,为了避免CMSThread占用大量CPU时间,影响到关键业务操作的执行;如果是前台GC,则一次性清空,其主要流程如下:

image.png

7、mark_sweep_phase1
其主要流程如下:

image.png

补充说明如下:

8、mark_sweep_phase2
mark_sweep_phase2的实现比较简单,就是依次调用老年代和年轻代对应Space的prepare_for_compaction方法,该方法用于计算对象复制的地址并将其写入对象头中,其主要流程如下:

image.png

计算对象复制地址并写入对象头是在CompactibleFreeListSpace::forward方法中实现的,其处理流程如下:

image.png

补充说明如下:

set_next_compaction_space方法的调用链如下:

image.png

9、mark_sweep_phase3
其主要处理流程如下:

image.png

补充说明如下:

10、mark_sweep_phase4
mark_sweep_phase4的实现比较简单,就是依次调用老年代和年轻代对应Space的compact方法,用于完成对象复制,重置bottom地址,其主要流程如下:


image.png
上一篇 下一篇

猜你喜欢

热点阅读