从零开始看源码,旨在从源码验证书上的结论,探索书上未知的细节。有疑问欢迎留言探讨
个人源码地址:https://github.com/FlashLightNing/openjdk-notes
还有一个openjdk6,7,8,9的地址:https://github.com/dmlloyd/openjdk
jvm源码阅读笔记[1]:如何触发一次CMS回收
jvm源码阅读笔记[2]:你不知道的晋升阈值TenuringThreshold详解
jvm源码阅读笔记[3]:从内存分配到触发GC的细节
jvm源码阅读笔记[4]:从GC说到vm operation
jvm源码阅读笔记[5]:内存分配失败触发的GC究竟对内存做了什么?
对于配置使用CMS回收器的应用,用jstack pid | grep GC 可以发现,有一个名为Concurrent Mark-Sweep GC Thread的线程。
这个线程的作用呢,就是每隔2秒钟,就检查一下老年代是否需要回收,如果需要,则就会进行一次CMS回收。为什么这么说呢?来看看这个线程对应的源码:源码地址
ConcurrentMarkSweepThread::ConcurrentMarkSweepThread(CMSCollector* collector)
: ConcurrentGCThread() {
assert(UseConcMarkSweepGC, "UseConcMarkSweepGC should be set");//表示在vm启动参数中必须加上UseConcMarkSweepGC
assert(_cmst == NULL, "CMS thread already created");
_cmst = this;
assert(_collector == NULL, "Collector already set");
_collector = collector;
//前面的这些assert主要是一些参数判断,保证这些参数符合条件。
set_name("Concurrent Mark-Sweep GC Thread");//可以看到在这设置了线程名称
if (os::create_thread(this, os::cgc_thread)) {
int native_prio;
if (UseCriticalCMSThreadPriority) {
//UseCriticalCMSThreadPriority默认false
native_prio = os::java_to_os_priority[CriticalPriority];
} else {
native_prio = os::java_to_os_priority[NearMaxPriority];
}
os::set_native_priority(this, native_prio);
if (!DisableStartThread) {
os::start_thread(this);
}
}
_sltMonitor = SLT_lock;
assert(!CMSIncrementalMode || icms_is_enabled(), "Error");
}
再来看看比较关键的线程的run()方法:
//线程的run方法
void ConcurrentMarkSweepThread::run() {
assert(this == cmst(), "just checking");
this->record_stack_base_and_size();
this->initialize_thread_local_storage();
this->set_active_handles(JNIHandleBlock::allocate_block());
// 检查是否为当前线程
assert(this == Thread::current(), "just checking");
if (BindCMSThreadToCPU && !os::bind_to_processor(CPUForCMSThread)) {
warning("Couldn't bind CMS thread to processor " UINTX_FORMAT, CPUForCMSThread);
}
{
CMSLoopCountWarn loopX("CMS::run", "waiting for "
"Universe