美團(tuán)面試:CMS(Concurrent Mark Sweep)GC的工作原理和致

易錯(cuò)點(diǎn):在用CMS做老年代的垃圾回收時(shí),GC Roots是一個(gè)廣義的GC Roots,包含年輕代的所有存活對(duì)象。
因此,在CMS的初始化標(biāo)記階段,除了標(biāo)記狹義的GC Roots到老年代的直接引用,還要標(biāo)記年輕代到老年代的直接引用。
JDK8源碼執(zhí)行路徑如下:
一 concurrentMarkSweepGeneration.cpp
定位到2343行,初始化標(biāo)記的入口:M_CMS_Initial_Mark initial_mark_op(this) ,進(jìn)一步跟進(jìn)去,進(jìn)入到第二步。
二 vmCMSOperations.cpp
跟進(jìn)去,找到:_collector->do_CMS_operation(CMSCollector::CMS_op_checkpointRootsInitial, gch->gc_cause());這行代碼,再進(jìn)入到第三步。
三 concurrentMarkSweepGeneration.cpp
① 定位到6636行(具體的初始標(biāo)記工作),checkpointRootsInitial(true);
再往下跟進(jìn),跟進(jìn)到3746行,也就是“② gen_process_strong_roots”
② gen_process_strong_roots
用來處理直接從gc root直達(dá)的對(duì)象。
// The serial version. CMKlassClosure klass_closure(¬Older); gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel. gch->gen_process_strong_roots(_cmsGen->level(), true, // younger gens are roots true, // activate StrongRootsScope false, // not scavenging SharedHeap::ScanningOption(roots_scanning_options()), ¬Older, true, // walk all of code cache if (so & SO_CodeCache) NULL, &klass_closure); }
跟著gen_process_roots下去后,可以看到gen_process_roots,用來處理直接從gc root直達(dá)的對(duì)象。
所以,現(xiàn)在搞清楚GC Roots的定義了,因此,在做CMS GC時(shí),GC Roots除了一般定義的節(jié)點(diǎn)外,還需要加上從年輕代到老年代的引用。