目錄
2、SurvivorSpacePrecleanClosure
4、ScanMarkedObjectsAgainCarefullyClosure
6、Precleaning 和 AbortablePreclean 總結
8、do_remark_parallel / do_remark_non_parallel
本篇博客繼續上一篇《Hotspot 垃圾回收之CMSCollector(三) 源碼解析》講解Precleaning和AbortablePreclean步驟依賴的相關Closure實現。
1、PushAndMarkClosure
PushAndMarkClosure用於遍歷survivor區的oop,其實現跟CMSKeepAliveClosure基本一致,如果該oop在BitMap未打標則打標,並將其放到_mark_stack中,如果_mark_stack滿了且_concurrent_precleaning爲false,則將其放到通過對象頭指針構成的鏈表overflow_list中;如果_mark_stack滿了且_concurrent_precleaning爲true,則在_mod_union_table中打標,注意如果對象是數組,則數組的起止位置之間內存區域都需要在_mod_union_table中打標。其實現如下:
PushAndMarkClosure::PushAndMarkClosure(CMSCollector* collector,
MemRegion span,
ReferenceProcessor* rp,
CMSBitMap* bit_map,
CMSBitMap* mod_union_table,
CMSMarkStack* mark_stack,
bool concurrent_precleaning):
MetadataAwareOopClosure(rp),
_collector(collector),
_span(span),
_bit_map(bit_map),
_mod_union_table(mod_union_table),
_mark_stack(mark_stack),
_concurrent_precleaning(concurrent_precleaning)
{
assert(_ref_processor != NULL, "_ref_processor shouldn't be NULL");
}
void PushAndMarkClosure::do_oop(oop obj) {
assert(obj->is_oop_or_null(true /* ignore mark word */),
"expected an oop or NULL");
HeapWord* addr = (HeapWord*)obj;
if (_span.contains(addr) && !_bit_map->isMarked(addr)) {
//如果BitMap未打標,則打標
_bit_map->mark(addr); // ... now grey
bool simulate_overflow = false;
if (simulate_overflow || !_mark_stack->push(obj)) {
//如果_mark_stack滿了,push失敗了
if (_concurrent_precleaning) {
if (obj->is_objArray()) {
size_t sz = obj->size();
HeapWord* end_card_addr = (HeapWord*)round_to(
(intptr_t)(addr+sz), CardTableModRefBS::card_size);
MemRegion redirty_range = MemRegion(addr, end_card_addr);
assert(!redirty_range.is_empty(), "Arithmetical tautology");
_mod_union_table->mark_range(redirty_range);
} else {
_mod_union_table->mark(addr);
}
_collector->_ser_pmc_preclean_ovflw++;
} else {
//_concurrent_precleaning爲false
_collector->push_on_overflow_list(obj);
_collector->_ser_pmc_remark_ovflw++;
}
}
}
}
2、SurvivorSpacePrecleanClosure
SurvivorSpacePrecleanClosure用來遍歷survivor的from和to區中包含的對象,對每個對象遍歷其所引用的其他對象,用PushAndMarkClosure來處理其他對象,PushAndMarkClosure會將其他對象放到_mark_stack中,然後SurvivorSpacePrecleanClosure再使用PushAndMarkClosure來處理_mark_stack中的對象,直到所引用的對象全部遍歷完成,其實現如下:
SurvivorSpacePrecleanClosure(CMSCollector* collector,
MemRegion span,
CMSBitMap* bit_map,
CMSMarkStack* mark_stack,
PushAndMarkClosure* cl,
unsigned int before_count,
bool should_yield):
_collector(collector),
_span(span),
_yield(should_yield),
_bit_map(bit_map),
_mark_stack(mark_stack),
_scanning_closure(cl),
_before_count(before_count)
{ }
size_t SurvivorSpacePrecleanClosure::do_object_careful(oop p) {
HeapWord* addr = (HeapWord*)p;
//span是老年代的內存區域,所以肯定不包含survivor區的對象地址
assert(!_span.contains(addr), "we are scanning the survivor spaces");
//校驗對象已初始化
assert(p->klass_or_null() != NULL, "object should be initializd");
assert(p->is_oop(true), "should be an oop");
//遍歷該對象所引用的其他對象,_scanning_closure處理其他對象時如果該對象未打標,會將其打標並加入到_mark_stack中
size_t size = p->oop_iterate(_scanning_closure);
//檢查是否需要yeild,如果需要則執行yeild
do_yield_check();
//如果_mark_stack非空
while (!_mark_stack->isEmpty()) {
//彈出一個待處理的oop
oop new_oop = _mark_stack->pop();
assert(new_oop != NULL && new_oop->is_oop(), "Expected an oop");
assert(_bit_map->isMarked((HeapWord*)new_oop),
"only grey objects on this stack");
//同樣的方式遍歷該oop所引用的其他oop
new_oop->oop_iterate(_scanning_closure);
//檢查是否需要yeild,如果需要則執行yeild
do_yield_check();
}
unsigned int after_count =
GenCollectedHeap::heap()->total_collections();
//如果should_abort_preclean爲true
bool abort = (_before_count != after_count) ||
_collector->should_abort_preclean();
return abort ? 0 : size;
}
inline void SurvivorSpacePrecleanClosure::do_yield_check() {
if (ConcurrentMarkSweepThread::should_yield() &&
!_collector->foregroundGCIsActive() &&
_yield) {
// Sample young gen size before and after yield
_collector->sample_eden();
do_yield_work();
_collector->sample_eden();
}
}
void SurvivorSpacePrecleanClosure::do_yield_work() {
assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
"CMS thread should hold CMS token");
assert_lock_strong(_bit_map->lock());
// Relinquish the bit map lock
_bit_map->lock()->unlock();
ConcurrentMarkSweepThread::desynchronize(true);
ConcurrentMarkSweepThread::acknowledge_yield_request();
_collector->stopTimer();
GCPauseTimer p(_collector->size_policy()->concurrent_timer_ptr());
if (PrintCMSStatistics != 0) {
_collector->incrementYields();
}
_collector->icms_wait();
// See the comment in coordinator_yield()
for (unsigned i = 0; i < CMSYieldSleepCount &&
ConcurrentMarkSweepThread::should_yield() &&
!CMSCollector::foregroundGCIsActive(); ++i) {
os::sleep(Thread::current(), 1, false);
ConcurrentMarkSweepThread::acknowledge_yield_request();
}
ConcurrentMarkSweepThread::synchronize(true);
_bit_map->lock()->lock_without_safepoint_check();
_collector->startTimer();
}
3、MarkRefsIntoAndScanClosure
MarkRefsIntoAndScanClosure的核心邏輯和SurvivorSpacePrecleanClosure基本相同,都是藉助PushAndMarkClosure不斷循環遍歷,實現以某個oop爲根節點,將該oop所引用的其他oop,其他oop所引用的其他oop全都遍歷一遍,直到沒有引用的oop了,其實現如下:
MarkRefsIntoAndScanClosure::MarkRefsIntoAndScanClosure(MemRegion span,
ReferenceProcessor* rp,
CMSBitMap* bit_map,
CMSBitMap* mod_union_table,
CMSMarkStack* mark_stack,
CMSCollector* collector,
bool should_yield,
bool concurrent_precleaning):
_collector(collector),
_span(span),
_bit_map(bit_map),
_mark_stack(mark_stack),
_pushAndMarkClosure(collector, span, rp, bit_map, mod_union_table,
mark_stack, concurrent_precleaning), //該屬性就是PushAndMarkClosure
_yield(should_yield),
_concurrent_precleaning(concurrent_precleaning),
_freelistLock(NULL)
{
_ref_processor = rp;
assert(_ref_processor != NULL, "_ref_processor shouldn't be NULL");
}
void MarkRefsIntoAndScanClosure::do_oop(oop obj) {
if (obj != NULL) {
assert(obj->is_oop(), "expected an oop");
HeapWord* addr = (HeapWord*)obj;
assert(_mark_stack->isEmpty(), "pre-condition (eager drainage)");
assert(_collector->overflow_list_is_empty(),
"overflow list should be empty");
if (_span.contains(addr) &&
!_bit_map->isMarked(addr)) {
//如果該對象未打標,則在bitMap中打標
_bit_map->mark(addr);
//將該對象放入_mark_stack
bool res = _mark_stack->push(obj);
assert(res, "Should have space to push on empty stack");
do {
oop new_oop = _mark_stack->pop();
assert(new_oop != NULL && new_oop->is_oop(), "Expected an oop");
assert(_bit_map->isMarked((HeapWord*)new_oop),
"only grey objects on this stack");
//使用_pushAndMarkClosure遍歷該對象所引用的其他oop,_pushAndMarkClosure會遍歷其他oop中的每個oop所引用的
//其他oop,把他們添加到_mark_stack中
new_oop->oop_iterate(&_pushAndMarkClosure);
//檢查是否需要yield,如果需要則執行yield動作
do_yield_check();
} while (!_mark_stack->isEmpty() || //_mark_stack爲空
(!_concurrent_precleaning && take_from_overflow_list())); //overflow_list爲空,兩者都滿足時終止循環
}
assert(_mark_stack->isEmpty(), "post-condition (eager drainage)");
assert(_collector->overflow_list_is_empty(),
"overflow list was drained above");
//CMSOverflowEarlyRestoration爲false,表示是否較早的恢復_preserved_oop_stack中保存的oop的對象頭
if (!_concurrent_precleaning && CMSOverflowEarlyRestoration) {
_collector->restore_preserved_marks_if_any();
assert(_collector->no_preserved_marks(), "No preserved marks");
}
assert(!CMSOverflowEarlyRestoration || _collector->no_preserved_marks(),
"All preserved marks should have been restored above");
}
}
inline void MarkRefsIntoAndScanClosure::do_yield_check() {
if (_yield &&
!_collector->foregroundGCIsActive() &&
ConcurrentMarkSweepThread::should_yield()) {
do_yield_work();
}
}
void MarkRefsIntoAndScanClosure::do_yield_work() {
assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
"CMS thread should hold CMS token");
assert_lock_strong(_freelistLock);
assert_lock_strong(_bit_map->lock());
// relinquish the free_list_lock and bitMaplock()
_bit_map->lock()->unlock();
_freelistLock->unlock();
ConcurrentMarkSweepThread::desynchronize(true);
ConcurrentMarkSweepThread::acknowledge_yield_request();
_collector->stopTimer();
GCPauseTimer p(_collector->size_policy()->concurrent_timer_ptr());
if (PrintCMSStatistics != 0) {
_collector->incrementYields();
}
_collector->icms_wait();
// See the comment in coordinator_yield()
for (unsigned i = 0;
i < CMSYieldSleepCount &&
ConcurrentMarkSweepThread::should_yield() &&
!CMSCollector::foregroundGCIsActive();
++i) {
os::sleep(Thread::current(), 1, false);
ConcurrentMarkSweepThread::acknowledge_yield_request();
}
ConcurrentMarkSweepThread::synchronize(true);
_freelistLock->lock_without_safepoint_check();
_bit_map->lock()->lock_without_safepoint_check();
_collector->startTimer();
}
bool MarkRefsIntoAndScanClosure::take_from_overflow_list() {
size_t num = MIN2((size_t)(_mark_stack->capacity() - _mark_stack->length())/4,
(size_t)ParGCDesiredObjsFromOverflowList);
//從overflow_list中取出最多num個待處理oop放入_mark_stack中
bool res = _collector->take_from_overflow_list(num, _mark_stack);
assert(_collector->overflow_list_is_empty() || res,
"If list is not empty, we should have taken something");
assert(!res || !_mark_stack->isEmpty(),
"If we took something, it should now be on our stack");
return res;
}
void CMSCollector::restore_preserved_marks_if_any() {
//校驗在安全點上
assert(SafepointSynchronize::is_at_safepoint(),
"world should be stopped");
assert(Thread::current()->is_ConcurrentGC_thread() ||
Thread::current()->is_VM_thread(),
"should be single-threaded");
assert(_preserved_oop_stack.size() == _preserved_mark_stack.size(),
"bijection");
while (!_preserved_oop_stack.is_empty()) {
//彈出oop
oop p = _preserved_oop_stack.pop();
assert(p->is_oop(), "Should be an oop");
assert(_span.contains(p), "oop should be in _span");
assert(p->mark() == markOopDesc::prototype(),
"Set when taken from overflow list");
//彈出對應的對象頭
markOop m = _preserved_mark_stack.pop();
//恢復原來的對象頭
p->set_mark(m);
}
assert(_preserved_mark_stack.is_empty() && _preserved_oop_stack.is_empty(),
"stacks were cleared above");
}
#ifndef PRODUCT
bool CMSCollector::no_preserved_marks() const {
return _preserved_mark_stack.is_empty() && _preserved_oop_stack.is_empty();
}
#endif
4、ScanMarkedObjectsAgainCarefullyClosure
ScanMarkedObjectsAgainCarefullyClosure用來遍歷從_modUnionTable或者卡表(CardTableModRefBS)中找到的髒的卡表項對應的內存區域中包含的對象,如果該對象已打標且完成初始化,則用MarkRefsIntoAndScanClosure遍歷該對象所引用的其他對象,否則的話跳過該對象,是preclean_mod_union_table和preclean_card_table中使用的遍歷方法。其實現如下:
ScanMarkedObjectsAgainCarefullyClosure(CMSCollector* collector,
MemRegion span,
CMSBitMap* bitMap,
CMSMarkStack* markStack,
MarkRefsIntoAndScanClosure* cl,
bool should_yield):
_collector(collector),
_span(span),
_yield(should_yield),
_bitMap(bitMap),
_markStack(markStack),
_scanningClosure(cl) {
}
size_t ScanMarkedObjectsAgainCarefullyClosure::do_object_careful_m(
oop p, MemRegion mr) {
size_t size = 0;
HeapWord* addr = (HeapWord*)p;
DEBUG_ONLY(_collector->verify_work_stacks_empty();)
assert(_span.contains(addr), "we are scanning the CMS generation");
// check if it's time to yield
if (do_yield_check()) {
//如果需要yield則執行yeild,yeild結束後should_abort_preclean返回true則終止執行
return 0;
}
if (_bitMap->isMarked(addr)) {
//addr已打標
if (p->klass_or_null() != NULL) {
//該oop已初始化
assert(p->is_oop(true), "should be an oop");
if (p->is_objArray()) {
//用MarkRefsIntoAndScanClosure來遍歷該數組所引用的其他對象,遍歷完成返回數組大小
size = CompactibleFreeListSpace::adjustObjectSize(
p->oop_iterate(_scanningClosure, mr));
} else {
//用MarkRefsIntoAndScanClosure來遍歷該對象所引用的其他對象,遍歷完成返回對象大小
size = CompactibleFreeListSpace::adjustObjectSize(
p->oop_iterate(_scanningClosure));
}
} else {
//該oop未初始化
assert(_bitMap->isMarked(addr+1), "missing Printezis mark?");
//獲取addr + 2之後的一個被打標的位,即該對象的結束地址,然後根據結束地址計算對象大小
HeapWord* nextOneAddr = _bitMap->getNextMarkedWordAddress(addr + 2);
size = pointer_delta(nextOneAddr + 1, addr);
assert(size == CompactibleFreeListSpace::adjustObjectSize(size),
"alignment problem");
}
} else {
//addr未打標
if (p->klass_or_null() == NULL) {
//klass爲NULL,未初始化的對象
assert(size == 0, "Initial value");
} else {
//klass不爲NULL,根據klass獲取對象大小
assert(p->is_oop(true), "should be an oop");
size = CompactibleFreeListSpace::adjustObjectSize(p->size());
}
}
return size;
}
inline bool ScanMarkedObjectsAgainCarefullyClosure::do_yield_check() {
if (ConcurrentMarkSweepThread::should_yield() &&
!_collector->foregroundGCIsActive() &&
_yield) {
// Sample young gen size before and after yield
_collector->sample_eden();
do_yield_work();
_collector->sample_eden();
return _collector->should_abort_preclean();
}
return false;
}
void ScanMarkedObjectsAgainCarefullyClosure::do_yield_work() {
assert(ConcurrentMarkSweepThread::cms_thread_has_cms_token(),
"CMS thread should hold CMS token");
assert_lock_strong(_freelistLock);
assert_lock_strong(_bitMap->lock());
// relinquish the free_list_lock and bitMaplock()
_bitMap->lock()->unlock();
_freelistLock->unlock();
ConcurrentMarkSweepThread::desynchronize(true);
ConcurrentMarkSweepThread::acknowledge_yield_request();
_collector->stopTimer();
GCPauseTimer p(_collector->size_policy()->concurrent_timer_ptr());
if (PrintCMSStatistics != 0) {
_collector->incrementYields();
}
_collector->icms_wait();
// See the comment in coordinator_yield()
for (unsigned i = 0; i < CMSYieldSleepCount &&
ConcurrentMarkSweepThread::should_yield() &&
!CMSCollector::foregroundGCIsActive(); ++i) {
os::sleep(Thread::current(), 1, false);
ConcurrentMarkSweepThread::acknowledge_yield_request();
}
ConcurrentMarkSweepThread::synchronize(true);
_freelistLock->lock_without_safepoint_check();
_bitMap->lock()->lock_without_safepoint_check();
_collector->startTimer();
}
5、PrecleanKlassClosure
PrecleanKlassClosure是preclean_klasses使用的,使用MarkRefsIntoAndScanClosure來遍歷發生修改的klass對應的類Class實例,其實現如下:
class PrecleanKlassClosure : public KlassClosure {
KlassToOopClosure _cm_klass_closure;
public:
PrecleanKlassClosure(OopClosure* oop_closure) : _cm_klass_closure(oop_closure) {}
void do_klass(Klass* k) {
if (k->has_accumulated_modified_oops()) {
k->clear_accumulated_modified_oops();
_cm_klass_closure.do_klass(k);
}
}
};
void KlassToOopClosure::do_klass(Klass* k) {
assert(_oop_closure != NULL, "Not initialized?");
k->oops_do(_oop_closure);
}
void Klass::oops_do(OopClosure* cl) {
cl->do_oop(&_java_mirror);
}
6、Precleaning 和 AbortablePreclean 總結
Precleaning和AbortablePreclean兩步都是後臺GC纔有的,不要求JVM處於安全點上,其底層核心都是同一個方法preclean_work,注意只有當CMSPrecleaningEnabled參數爲true時,後臺GC纔會由Precleaning流轉到AbortablePreclean狀態,否則直接進入到FinalMarking狀態,該參數默認爲true。Precleaning時只執行一遍preclean_work,並且preclean_work會清理查找到的Reference實例;AbortablePreclean會執行多次preclean_work,並且preclean_work會遍歷survivor區中的對象,當達到某個條件時才退出。
這兩個步驟涉及兩個重要屬性,_start_sampling和_abort_preclean,前者表示是否需要採集eden區的top地址,後者表示是否需要終止preclean,兩者在CMSCollector初始化時都是爲false。_start_sampling在preclean方法中根據eden區的內存使用率決定,默認配置下只有使用率低於10%的時候纔會將_start_sampling置爲true,否則爲false。_abort_preclean只在sample_eden方法中修改,在_start_sampling爲true且eden區內存使用率大於50%時才置爲true,如果_start_sampling爲false,則sample_eden方法直接返回,即這種情形下_abort_preclean始終爲false。讀取_abort_preclean屬性的只有一個方法should_abort_preclean,其實現如下:
其調用鏈如下:
7、checkpointRootsFinal
checkpointRootsFinal方法用來實現FinalMarking步驟的,該方法主要用於執行二次打標,清理Reference實例,如果需要卸載Class,還要清理符號表,字符串表,CodeCache中被卸載類的相關元數據。其中二次打標是在後臺GC執行了InitialMarking的情形下才執行,因爲從後臺GC執行完InitialMarking到FinalMarking期間引用關係可能發生了改變,需要二次打標;如果是前臺GC執行了InitialMarking,即前臺GC完整的執行了整個GC過程則不需要二次打標,因爲前臺GC都是在JVM處於安全點,stop the world的狀態下執行的,引用關係不會再發生改變。
void CMSCollector::checkpointRootsFinal(bool asynch,
bool clear_all_soft_refs, bool init_mark_was_synchronous) {
assert(_collectorState == FinalMarking, "incorrect state transition?");
check_correct_thread_executing();
// world is stopped at this checkpoint
assert(SafepointSynchronize::is_at_safepoint(),
"world should be stopped");
TraceCMSMemoryManagerStats tms(_collectorState,GenCollectedHeap::heap()->gc_cause());
verify_work_stacks_empty();
verify_overflow_empty();
SpecializationStats::clear();
if (PrintGCDetails) {
gclog_or_tty->print("[YG occupancy: " SIZE_FORMAT " K (" SIZE_FORMAT " K)]",
_young_gen->used() / K,
_young_gen->capacity() / K);
}
if (asynch) {
//異步GC
//CMSScavengeBeforeRemark表示是否嘗試在remark前掃描一遍年輕代,默認爲false
if (CMSScavengeBeforeRemark) {
GenCollectedHeap* gch = GenCollectedHeap::heap();
//gch->do_collection希望_is_gc_active爲false
FlagSetting fl(gch->_is_gc_active, false);
int level = _cmsGen->level() - 1;
if (level >= 0) {
//這裏實際是清理年輕代
gch->do_collection(true, // full (i.e. force, see below)
false, // !clear_all_soft_refs
0, // size
false, // is_tlab
level // max_level
);
}
}
//獲取FreelistLock和bitMapLock
FreelistLocker x(this);
MutexLockerEx y(bitMapLock(),
Mutex::_no_safepoint_check_flag);
assert(!init_mark_was_synchronous, "but that's impossible!");
checkpointRootsFinalWork(asynch, clear_all_soft_refs, false);
} else {
//同步GC
checkpointRootsFinalWork(asynch, clear_all_soft_refs,
init_mark_was_synchronous);
}
verify_work_stacks_empty();
verify_overflow_empty();
SpecializationStats::print();
}
void CMSCollector::checkpointRootsFinalWork(bool asynch,
bool clear_all_soft_refs, bool init_mark_was_synchronous) {
//校驗獲取了鎖
assert(haveFreelistLocks(), "must have free list locks");
assert_lock_strong(bitMapLock());
if (UseAdaptiveSizePolicy) {
//通知checkpoint_roots_final步驟開始
size_policy()->checkpoint_roots_final_begin();
}
ResourceMark rm;
HandleMark hm;
GenCollectedHeap* gch = GenCollectedHeap::heap();
if (should_unload_classes()) {
//如果需要卸載類,則執行CodeCache的GC預處理
CodeCache::gc_prologue();
}
assert(haveFreelistLocks(), "must have free list locks");
assert_lock_strong(bitMapLock());
if (!init_mark_was_synchronous) {
//init_mark_was_synchronous爲false
//確保TLAB不會被釋放掉
gch->ensure_parsability(false); // fill TLAB's, but no need to retire them
//保存各代的save_mark
gch->save_marks();
if (CMSPrintEdenSurvivorChunks) {
print_eden_and_survivor_chunk_arrays();
}
{
COMPILER2_PRESENT(DerivedPointerTableDeactivate dpt_deact;)
//CMSParallelRemarkEnabled默認是爲true,表示是否並行執行Remark
if (CMSParallelRemarkEnabled && CollectedHeap::use_parallel_gc_threads()) {
GCTraceTime t("Rescan (parallel) ", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
do_remark_parallel();
} else {
GCTraceTime t("Rescan (non-parallel) ", PrintGCDetails, false,
_gc_timer_cm, _gc_tracer_cm->gc_id());
do_remark_non_parallel();
}
}
} else {
//init_mark_was_synchronous爲true,表示執行InitialMarking是同步的,會stop the word
//如果是同步GC執行的InitialMarking,則init_mark_was_synchronous爲true,同步GC的整個過程都會stop the world
//如果是異步GC執行的InitialMarking,或者是異步GC執行checkpointRootsFinal方法,則init_mark_was_synchronous爲false
assert(!asynch, "Can't have init_mark_was_synchronous in asynch mode");
}
verify_work_stacks_empty();
verify_overflow_empty();
{
//處理查找的Reference實例,執行Klass卸載,符號表,字符串表,CodeCache清理,最後將剩餘的Reference實例放入Reference類的pending_list中
refProcessingWork(asynch, clear_all_soft_refs);
}
verify_work_stacks_empty();
verify_overflow_empty();
if (should_unload_classes()) {
//執行CodeCache的gc後處理
CodeCache::gc_epilogue();
}
JvmtiExport::gc_epilogue();
assert(_markStack.isEmpty(), "No grey objects");
size_t ser_ovflw = _ser_pmc_remark_ovflw + _ser_pmc_preclean_ovflw +
_ser_kac_ovflw + _ser_kac_preclean_ovflw;
if (ser_ovflw > 0) {
if (PrintCMSStatistics != 0) {
gclog_or_tty->print_cr("Marking stack overflow (benign) "
"(pmc_pc=" SIZE_FORMAT ", pmc_rm=" SIZE_FORMAT ", kac=" SIZE_FORMAT
", kac_preclean=" SIZE_FORMAT ")",
_ser_pmc_preclean_ovflw, _ser_pmc_remark_ovflw,
_ser_kac_ovflw, _ser_kac_preclean_ovflw);
}
//_markStack擴容
_markStack.expand();
//計數置0
_ser_pmc_remark_ovflw = 0;
_ser_pmc_preclean_ovflw = 0;
_ser_kac_preclean_ovflw = 0;
_ser_kac_ovflw = 0;
}
if (_par_pmc_remark_ovflw > 0 || _par_kac_ovflw > 0) {
if (PrintCMSStatistics != 0) {
gclog_or_tty->print_cr("Work queue overflow (benign) "
"(pmc_rm=" SIZE_FORMAT ", kac=" SIZE_FORMAT ")",
_par_pmc_remark_ovflw, _par_kac_ovflw);
}
//計數置0
_par_pmc_remark_ovflw = 0;
_par_kac_ovflw = 0;
}
if (PrintCMSStatistics != 0) {
if (_markStack._hit_limit > 0) {
gclog_or_tty->print_cr(" (benign) Hit max stack size limit (" SIZE_FORMAT ")",
_markStack._hit_limit);
}
if (_markStack._failed_double > 0) {
gclog_or_tty->print_cr(" (benign) Failed stack doubling (" SIZE_FORMAT "),"
" current capacity " SIZE_FORMAT,
_markStack._failed_double,
_markStack.capacity());
}
}
//計數置0
_markStack._hit_limit = 0;
_markStack._failed_double = 0;
if ((VerifyAfterGC || VerifyDuringGC) &&
GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
verify_after_remark();
}
_gc_tracer_cm->report_object_count_after_gc(&_is_alive_closure);
//修改狀態
_collectorState = Sweeping;
// Call isAllClear() under bitMapLock
assert(_modUnionTable.isAllClear(),
"Should be clear by end of the final marking");
assert(_ct->klass_rem_set()->mod_union_is_clear(),
"Should be clear by end of the final marking");
if (UseAdaptiveSizePolicy) {
//通知checkpoint_roots_final操作結束
size_policy()->checkpoint_roots_final_end(gch->gc_cause());
}
}
8、do_remark_parallel / do_remark_non_parallel
這兩方法就是checkpointRootsFinal中用於多線程和單線程下執行二次打標的方法,兩者遍歷打標邏輯基本一致,跟InitialMarking的遍歷打標邏輯也基本相同。
void CMSCollector::do_remark_parallel() {
GenCollectedHeap* gch = GenCollectedHeap::heap();
FlexibleWorkGang* workers = gch->workers();
assert(workers != NULL, "Need parallel worker threads.");
//設置並行的GC線程數
int n_workers = workers->active_workers();
if (n_workers == 0) {
assert(n_workers > 0, "Should have been set during scavenge");
n_workers = ParallelGCThreads;
workers->set_active_workers(n_workers);
}
CompactibleFreeListSpace* cms_space = _cmsGen->cmsSpace();
CMSParRemarkTask tsk(this,
cms_space,
n_workers, workers, task_queues());
// Set up for parallel process_roots work.
gch->set_par_threads(n_workers);
//初始化年輕代三個區的SequentialSubTasksDone
initialize_sequential_subtasks_for_young_gen_rescan(n_workers);
//初始化老年代的SequentialSubTasksDone
cms_space->initialize_sequential_subtasks_for_rescan(n_workers);
if (n_workers > 1) {
//臨時設置discovery_is_mt屬性爲true
ReferenceProcessorMTDiscoveryMutator mt(ref_processor(), true);
GenCollectedHeap::StrongRootsScope srs(gch);
//執行任務
workers->run_task(&tsk);
} else {
//臨時設置discovery_is_mt屬性爲false
ReferenceProcessorMTDiscoveryMutator mt(ref_processor(), false);
GenCollectedHeap::StrongRootsScope srs(gch);
tsk.work(0);
}
gch->set_par_threads(0); // 0 ==> non-parallel.
//恢復_preserved_oop_stack中保存的oop的對象頭
restore_preserved_marks_if_any();
}
void
CompactibleFreeListSpace::
initialize_sequential_subtasks_for_rescan(int n_threads) {
// The "size" of each task is fixed according to rescan_task_size.
assert(n_threads > 0, "Unexpected n_threads argument");
const size_t task_size = rescan_task_size();
//根據rescan_task_size和已使用內存,計算需要的任務數
size_t n_tasks = (used_region().word_size() + task_size - 1)/task_size;
assert((n_tasks == 0) == used_region().is_empty(), "n_tasks incorrect");
assert(n_tasks == 0 ||
((used_region().start() + (n_tasks - 1)*task_size < used_region().end()) &&
(used_region().start() + n_tasks*task_size >= used_region().end())),
"n_tasks calculation incorrect");
SequentialSubTasksDone* pst = conc_par_seq_tasks();
assert(!pst->valid(), "Clobbering existing data?");
//設置所需的線程數和任務數
pst->set_n_threads(n_threads);
pst->set_n_tasks((int)n_tasks);
}
const size_t rescan_task_size() const { return _rescan_task_size; }
void CMSCollector::do_remark_non_parallel() {
ResourceMark rm;
HandleMark hm;
GenCollectedHeap* gch = GenCollectedHeap::heap();
//臨時設置discovery_is_mt屬性爲false
ReferenceProcessorMTDiscoveryMutator mt(ref_processor(), false);
MarkRefsIntoAndScanClosure
mrias_cl(_span, ref_processor(), &_markBitMap, NULL /* not precleaning */,
&_markStack, this,
false /* should_yield */, false /* not precleaning */);
MarkFromDirtyCardsClosure
markFromDirtyCardsClosure(this, _span,
NULL, // space is set further below
&_markBitMap, &_markStack, &mrias_cl);
{
GCTraceTime t("grey object rescan", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
{
ModUnionClosure modUnionClosure(&_modUnionTable);
//遍歷卡表,將髒的卡表項對應的地址在mod union table中打標
_ct->ct_bs()->dirty_card_iterate(
_cmsGen->used_region(),
&modUnionClosure);
}
const int alignment =
CardTableModRefBS::card_size * BitsPerWord;
{
// ... First handle dirty cards in CMS gen
markFromDirtyCardsClosure.set_space(_cmsGen->cmsSpace());
MemRegion ur = _cmsGen->used_region();
HeapWord* lb = ur.start();
HeapWord* ub = (HeapWord*)round_to((intptr_t)ur.end(), alignment);
MemRegion cms_span(lb, ub);
//遍歷_modUnionTable中被打標的位,即髒的卡表項對應的內存區域中的對象,以他們爲根對象遍歷所有引用的對象,將其在BitMap中打標
_modUnionTable.dirty_range_iterate_clear(cms_span,
&markFromDirtyCardsClosure);
verify_work_stacks_empty();
if (PrintCMSStatistics != 0) {
gclog_or_tty->print(" (re-scanned " SIZE_FORMAT " dirty cards in cms gen) ",
markFromDirtyCardsClosure.num_dirty_cards());
}
}
}
if (VerifyDuringGC &&
GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
HandleMark hm; // Discard invalid handles created during verification
Universe::verify();
}
{
GCTraceTime t("root rescan", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
verify_work_stacks_empty();
gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
GenCollectedHeap::StrongRootsScope srs(gch);
//以年輕代的對象作爲根節點遍歷老年代
gch->gen_process_roots(_cmsGen->level(),
true, // younger gens as roots
false, // use the local StrongRootsScope
GenCollectedHeap::ScanningOption(roots_scanning_options()),
should_unload_classes(),
&mrias_cl,
NULL,
NULL); // The dirty klasses will be handled below
assert(should_unload_classes()
|| (roots_scanning_options() & GenCollectedHeap::SO_AllCodeCache),
"if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops");
}
{
GCTraceTime t("visit unhandled CLDs", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
verify_work_stacks_empty();
//遍歷新創建的ClassLoaderData
ResourceMark rm;
GrowableArray<ClassLoaderData*>* array = ClassLoaderDataGraph::new_clds();
for (int i = 0; i < array->length(); i++) {
mrias_cl.do_class_loader_data(array->at(i));
}
// We don't need to keep track of new CLDs anymore.
ClassLoaderDataGraph::remember_new_clds(false);
verify_work_stacks_empty();
}
{
GCTraceTime t("dirty klass scan", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
verify_work_stacks_empty();
RemarkKlassClosure remark_klass_closure(&mrias_cl);
//遍歷所有發生修改的Klass
ClassLoaderDataGraph::classes_do(&remark_klass_closure);
verify_work_stacks_empty();
}
verify_work_stacks_empty();
// Restore evacuated mark words, if any, used for overflow list links
if (!CMSOverflowEarlyRestoration) {
restore_preserved_marks_if_any();
}
verify_overflow_empty();
}
9、refProcessingWork
refProcessingWork是checkpointRootsFinal中用於處理Reference實例,並將剩餘的Reference實例插入到Reference類維護的pending list鏈表中,如果需要卸載類,還要清理SystemDictionary,CodeCache,SymbolTable和StringTable中與被卸載類的相關的元數據。
void CMSCollector::refProcessingWork(bool asynch, bool clear_all_soft_refs) {
ResourceMark rm;
HandleMark hm;
ReferenceProcessor* rp = ref_processor();
assert(rp->span().equals(_span), "Spans should be equal");
assert(!rp->enqueuing_is_done(), "Enqueuing should not be complete");
// Process weak references.
rp->setup_policy(clear_all_soft_refs);
verify_work_stacks_empty();
CMSKeepAliveClosure cmsKeepAliveClosure(this, _span, &_markBitMap,
&_markStack, false /* !preclean */);
CMSDrainMarkingStackClosure cmsDrainMarkingStackClosure(this,
_span, &_markBitMap, &_markStack,
&cmsKeepAliveClosure, false /* !preclean */);
{
GCTraceTime t("weak refs processing", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
ReferenceProcessorStats stats;
if (rp->processing_is_mt()) {
GenCollectedHeap* gch = GenCollectedHeap::heap();
//獲取並行執行的線程數
int active_workers = ParallelGCThreads;
FlexibleWorkGang* workers = gch->workers();
if (workers != NULL) {
active_workers = workers->active_workers();
assert(active_workers > 0, "Should have been set during scavenge");
}
rp->set_active_mt_degree(active_workers);
//初始化執行並行清理的執行器
CMSRefProcTaskExecutor task_executor(*this);
//處理所有找到的Reference實例
stats = rp->process_discovered_references(&_is_alive_closure,
&cmsKeepAliveClosure,
&cmsDrainMarkingStackClosure,
&task_executor,
_gc_timer_cm,
_gc_tracer_cm->gc_id());
} else {
stats = rp->process_discovered_references(&_is_alive_closure,
&cmsKeepAliveClosure,
&cmsDrainMarkingStackClosure,
NULL,
_gc_timer_cm,
_gc_tracer_cm->gc_id());
}
_gc_tracer_cm->report_gc_reference_stats(stats);
}
// This is the point where the entire marking should have completed.
verify_work_stacks_empty();
if (should_unload_classes()) {
{
//如果需要卸載類
GCTraceTime t("class unloading", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
//清理SystemDictionary
bool purged_class = SystemDictionary::do_unloading(&_is_alive_closure);
//清理CodeCache
CodeCache::do_unloading(&_is_alive_closure, purged_class);
//清理不再使用的klass
Klass::clean_weak_klass_links(&_is_alive_closure);
}
{
GCTraceTime t("scrub symbol table", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
//清理不再使用的符號引用
SymbolTable::unlink();
}
{
GCTraceTime t("scrub string table", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
//清理不再使用的字符串
StringTable::unlink(&_is_alive_closure);
}
}
//恢復_preserved_oop_stack中保存的oop的對象頭
restore_preserved_marks_if_any(); // done single-threaded for now
rp->set_enqueuing_is_done(true);
//將剩餘的Reference實例放入到Reference的pending_list中
if (rp->processing_is_mt()) {
rp->balance_all_queues();
CMSRefProcTaskExecutor task_executor(*this);
rp->enqueue_discovered_references(&task_executor);
} else {
rp->enqueue_discovered_references(NULL);
}
rp->verify_no_references_recorded();
assert(!rp->discovery_enabled(), "should have been disabled");
}