Hotspot 垃圾回收之ConcurrentMarkSweepThread 源码解析

   目录

一、ConcurrentGCThread

二、SurrogateLockerThread

1、make

2、loop / manipulatePLL

三、ConcurrentMarkSweepThread

1、定义

2、start和构造方法

3、run

4、CMSSynchronousYieldRequest / asynchronous_yield_request / acknowledge_yield_request / should_yield

5、stop_icms / icms_wait / start_icms 

6、synchronize / desynchronize 

7、CMSTokenSync / CMSTokenSyncWithLocks

8、stop / threads_do


本篇博客讲解在后台执行CMS GC的ConcurrentMarkSweepThread的实现。

一、ConcurrentGCThread

     ConcurrentGCThread表示一个并行GC的线程,其定义在hotspot\src\share\vm\gc_implementation\shared\concurrentGCThread.hpp中,在NamedThread的基础上添加了如下属性:

  •   bool _should_terminate; //是否应该终止
  •   bool _has_terminated; //是否已经终止
  •   static int _CGC_flag; //GC的标志

 _CGC_flag的取值有一个专门的枚举,其定义如下:

 初始值为CGC_nil,重点关注以下方法的实现:

  • create_and_start: 创建一个与之绑定的本地线程,设置优先级并启动执行
  • initialize_in_thread:初始化ConcurrentGCThread本身,记录线程栈基地址和大小,初始化TLAB等
  • wait_for_universe_init: 不断循环等待Universe初始化完成
  • terminate: 终止当前ConcurrentGCThread的执行
ConcurrentGCThread::ConcurrentGCThread() :
  _should_terminate(false), _has_terminated(false) {
};

//用于创建关联的本地线程并启动
void ConcurrentGCThread::create_and_start() {
  //创建关联的本地线程
  if (os::create_thread(this, os::cgc_thread)) {
    //设置优先级
    os::set_priority(this, NearMaxPriority);
    //DisableStartThread的默认值是false
    if (!_should_terminate && !DisableStartThread) {
      //启动本地线程
      os::start_thread(this);
    }
  }
}

void ConcurrentGCThread::initialize_in_thread() {
  //记录线程栈的基地址和大小
  this->record_stack_base_and_size();
  //初始化线程的本地存储空间TLAB
  this->initialize_thread_local_storage();
  //设置JNIHandleBlock
  this->set_active_handles(JNIHandleBlock::allocate_block());
  // From this time Thread::current() should be working.
  assert(this == Thread::current(), "just checking");
}

void ConcurrentGCThread::wait_for_universe_init() {
  //获取锁CGC_lock
  MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
  //不断循环,每隔200ms检查一次universe是否初始化完成
  while (!is_init_completed() && !_should_terminate) {
    CGC_lock->wait(Mutex::_no_safepoint_check_flag, 200);
  }
}

void ConcurrentGCThread::terminate() {
  {
    //获取锁Terminator_lock
    MutexLockerEx mu(Terminator_lock,
                     Mutex::_no_safepoint_check_flag);
    _has_terminated = true;
    Terminator_lock->notify();
  }
  //解除跟本地线程的关联,即终止本地线程
  ThreadLocalStorage::set_thread(NULL);
}

各方法的调用链如下:

 

 

 

从上述调用链可知,上述方法主要是G1算法在用。

二、SurrogateLockerThread

     SurrogateLockerThread表示一个用来操作Java Monitor锁的线程,其定义也在concurrentGCThread.hpp中,其类继承关系如下:

 其新增的属性如下:

  •   SLT_msg_type  _buffer;  // 执行的动作类型
  •   Monitor       _monitor; // 负责同步的锁
  •   BasicLock     _basicLock; // 实际未使用

 SLT_msg_type是一个枚举,其定义如下:

重点关注以下方法的实现。

1、make

    make方法用于创建一个SurrogateLockerThread,将其与一个java.lang.Thread实例绑定,并启动线程的执行,其实现如下:

SurrogateLockerThread* SurrogateLockerThread::make(TRAPS) {
  //获取java_lang_Thread对应的Klass
  Klass* k =
    SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(),
                                      true, CHECK_NULL);
  instanceKlassHandle klass (THREAD, k);
  //thread_oop用于保存创建的线程实例
  instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_NULL);

  const char thread_name[] = "Surrogate Locker Thread (Concurrent GC)";
  Handle string = java_lang_String::create_from_str(thread_name, CHECK_NULL);

  // Initialize thread_oop to put it into the system threadGroup
  Handle thread_group (THREAD, Universe::system_thread_group());
  JavaValue result(T_VOID);
  //调用构造方法 Thread(ThreadGroup group, String name) 创建一个Thread实例,结果保存在thread_oop中
  JavaCalls::call_special(&result, thread_oop,
                          klass,
                          vmSymbols::object_initializer_name(), //构造方法的方法名
                          vmSymbols::threadgroup_string_void_signature(), //构造方法的方法签名
                          thread_group,//两个参数
                          string,
                          CHECK_NULL);

  SurrogateLockerThread* res;
  {
    MutexLocker mu(Threads_lock);
    res = new SurrogateLockerThread();

    if (res == NULL || res->osthread() == NULL) {
      //res创建或者初始化失败,通常是因为内存不足导致的
      vm_exit_during_initialization("java.lang.OutOfMemoryError",
                                    "unable to create new native thread");
    }
    //将Thread实例同res关联起来,底层是设置Thread的eetop属性,该属性就是关联的C++线程对象的地址
    java_lang_Thread::set_thread(thread_oop(), res);
    //设置Thread实例的优先级
    java_lang_Thread::set_priority(thread_oop(), NearMaxPriority);
    //设置Thread实例的daemon属性
    java_lang_Thread::set_daemon(thread_oop());
    //res与Thread实例关联
    res->set_threadObj(thread_oop());
    //添加到Threads中保存的线程链表
    Threads::add(res);
    //启动res线程的执行,即构造时传入的_sltLoop方法
    Thread::start(res);
  }
  os::yield(); // This seems to help with initial start-up of SLT
  return res;
}

SurrogateLockerThread::SurrogateLockerThread() :
  JavaThread(&_sltLoop), //_sltLoop就是该线程执行的逻辑,即Run方法,JavaThread构造方法中会负责初始化相关属性并创建关联的本地线程
  _monitor(Mutex::nonleaf, "SLTMonitor"),
  _buffer(empty)
{}

static void _sltLoop(JavaThread* thread, TRAPS) {
  SurrogateLockerThread* slt = (SurrogateLockerThread*)thread;
  slt->loop();
}

其调用链如下:

Threads::create_vm中的调用如下图:

 

无论CMS算法还是G1算法,SurrogateLockerThread指针都是静态属性,即只有一个SurrogateLockerThread实例。

2、loop / manipulatePLL

      manipulatePLL会修改_buffer属性,然后释放锁等待loop方法执行完成相应的动作,loop方法不断循环,根据_buffer属性的值执行加锁和释放锁,执行完成将buffer属性重置为empty,其实现如下:

void SurrogateLockerThread::loop() {
  //pll是pending list lock的简称
  BasicLock pll_basic_lock;
  SLT_msg_type msg;
  debug_only(unsigned int owned = 0;)

  while (/* !isTerminated() */ 1) {
    {
      MutexLocker x(&_monitor);
      assert(!SafepointSynchronize::is_at_safepoint(),
             "SLT is a JavaThread");
      //等待msg变成非empty
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值