目录
4、CMSSynchronousYieldRequest / asynchronous_yield_request / acknowledge_yield_request / should_yield
5、stop_icms / icms_wait / start_icms
7、CMSTokenSync / CMSTokenSyncWithLocks
本篇博客讲解在后台执行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