本文讲解讲解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,其实现如下:
image.png
其调用链如下:
image.png
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");
}
网友评论