目录

1、定义

2、构造方法 / initialize / post_initialize

3、do_collection

4、do_full_collection

5、collect

6、VM_GenCollectFullConcurrent / VM_GenCollectFull

7、gen_process_roots / gen_process_weak_roots


之前的多篇博客已经陆陆续续将GenCollectedHeap依赖的相关实现类都讲解完了,本篇开始讲解表示分代堆内存的GenCollectedHeap的实现细节。

1、定义

GenCollectedHeap的定义在hotspot\src\share\vm\memory\genCollectedHeap.hpp中,其类继承关系如下:

其中CollectedHeap的讲解参考《Hotspot 垃圾回收之CollectedHeap 源码解析》 ,SharedHeap新增的属性如下:

  • static SharedHeap* _sh; //静态SharedHeap实例
  • GenRemSet* _rem_set; //卡表实现
  • CollectorPolicy *_collector_policy; //垃圾回收策略
  • int _strong_roots_parity; //遍历Java线程包含的oop使用的
  • FlexibleWorkGang* _workers; //执行并行GC的线程池
  • bool _thread_holds_heap_lock_for_gc;

GenCollectedHeap新增的属性如下:

  • static GenCollectedHeap* _gch; //静态GenCollectedHeap实例
  • int _n_gens; //包含的Generation的个数,通常是2
  • Generation* _gens[max_gens]; //Generation数组
  • GenerationSpec** _gen_specs; //用来初始化Generation的GenerationSpec数组
  • GenCollectorPolicy* _gen_policy; //垃圾回收策略
  • bool _incremental_collection_failed; // 执行promote是否会失败
  • unsigned int _full_collections_completed; //已经执行万恒的Full GC的次数
  • SubTasksDone* _process_strong_tasks; //用于控制根节点遍历任务的并行执行

其中max_gens是一个常量枚举,其定义如下:

除此之外还有一个表示并行执行任务的序号的枚举GCH_strong_roots_tasks,其定义如下:

重点关垃圾回收相关方法的实现。

2、构造方法 / initialize / post_initialize

这三个方法按照顺序依次调用,用来初始化GenCollectedHeap,其实现如下:

GenCollectedHeap::GenCollectedHeap(GenCollectorPolicy *policy) :SharedHeap(policy),_gen_policy(policy),_process_strong_tasks(new SubTasksDone(GCH_PS_NumElements)),_full_collections_completed(0)
{assert(policy != NULL, "Sanity check");
}SharedHeap::SharedHeap(CollectorPolicy* policy_) :CollectedHeap(),_collector_policy(policy_),_rem_set(NULL),_strong_roots_parity(0),_workers(NULL)
{//初始化静态属性_sh_sh = this;  // ch is static, should be set only once.if ((UseParNewGC ||(UseConcMarkSweepGC && (CMSParallelInitialMarkEnabled ||CMSParallelRemarkEnabled)) ||UseG1GC) &&ParallelGCThreads > 0) {//初始化执行并行GC的线程池  _workers = new FlexibleWorkGang("Parallel GC Threads", ParallelGCThreads,/* are_GC_task_threads */true,/* are_ConcurrentGC_threads */false);if (_workers == NULL) {vm_exit_during_initialization("Failed necessary allocation.");} else {_workers->initialize_workers();}}
}GenCollectedHeap::GenCollectedHeap(GenCollectorPolicy *policy) :SharedHeap(policy),_gen_policy(policy),_process_strong_tasks(new SubTasksDone(GCH_PS_NumElements)),_full_collections_completed(0)
{assert(policy != NULL, "Sanity check");
}jint GenCollectedHeap::initialize() {CollectedHeap::pre_initialize();int i;//_n_gens表示有多少代,通常是2代,年轻代和老年代_n_gens = gen_policy()->number_of_generations();guarantee(HeapWordSize == wordSize, "HeapWordSize must equal wordSize");size_t gen_alignment = Generation::GenGrain;_gen_specs = gen_policy()->generations();for (i = 0; i < _n_gens; i++) {//将内存的初始值和最大值按照内存分配粒度对齐_gen_specs[i]->align(gen_alignment);}char* heap_address;size_t total_reserved = 0;int n_covered_regions = 0;ReservedSpace heap_rs;size_t heap_alignment = collector_policy()->heap_alignment();//根据各GenerationSpec的最大大小计算总的需要保留的内存空间,然后申请指定大小的连续内存空间heap_address = allocate(heap_alignment, &total_reserved,&n_covered_regions, &heap_rs);if (!heap_rs.is_reserved()) {//申请失败vm_shutdown_during_initialization("Could not reserve enough space for object heap");return JNI_ENOMEM;}//设置_reserved相关属性_reserved = MemRegion((HeapWord*)heap_rs.base(),(HeapWord*)(heap_rs.base() + heap_rs.size()));_reserved.set_word_size(0);_reserved.set_start((HeapWord*)heap_rs.base());size_t actual_heap_size = heap_rs.size();_reserved.set_end((HeapWord*)(heap_rs.base() + actual_heap_size));//初始化GenRemSet_rem_set = collector_policy()->create_rem_set(_reserved, n_covered_regions);set_barrier_set(rem_set()->bs());_gch = this;for (i = 0; i < _n_gens; i++) {//初始化各GenerationReservedSpace this_rs = heap_rs.first_part(_gen_specs[i]->max_size(), false, false);_gens[i] = _gen_specs[i]->init(this_rs, i, rem_set());heap_rs = heap_rs.last_part(_gen_specs[i]->max_size());}//将_incremental_collection_failed置为falseclear_incremental_collection_failed();#if INCLUDE_ALL_GCSif (collector_policy()->is_concurrent_mark_sweep_policy()) {//如果是CMS则创建CMSCollectorbool success = create_cms_collector();if (!success) return JNI_ENOMEM;}
#endif // INCLUDE_ALL_GCSreturn JNI_OK;
}char* GenCollectedHeap::allocate(size_t alignment,size_t* _total_reserved,int* _n_covered_regions,ReservedSpace* heap_rs){const char overflow_msg[] = "The size of the object heap + VM data exceeds ""the maximum representable size";// Now figure out the total size.size_t total_reserved = 0;int n_covered_regions = 0;const size_t pageSize = UseLargePages ?os::large_page_size() : os::vm_page_size();assert(alignment % pageSize == 0, "Must be");//遍历所有的_gen_specs,累加各GenerationSpec的max_size和n_covered_regionsfor (int i = 0; i < _n_gens; i++) {total_reserved += _gen_specs[i]->max_size();if (total_reserved < _gen_specs[i]->max_size()) {vm_exit_during_initialization(overflow_msg);}n_covered_regions += _gen_specs[i]->n_covered_regions();}//校验累加后的total_reserved已经是内存对齐的assert(total_reserved % alignment == 0,err_msg("Gen size; total_reserved=" SIZE_FORMAT ", alignment="SIZE_FORMAT, total_reserved, alignment));//加2是为卡表保留的n_covered_regions += 2;//赋值*_total_reserved = total_reserved;*_n_covered_regions = n_covered_regions;//申请指定大小的连续内存空间*heap_rs = Universe::reserve_heap(total_reserved, alignment);//返回基地址return heap_rs->base();
}void SharedHeap::set_barrier_set(BarrierSet* bs) {_barrier_set = bs;oopDesc::set_bs(bs);
}void clear_incremental_collection_failed() {_incremental_collection_failed = false;}void GenCollectedHeap::post_initialize() {SharedHeap::post_initialize();TwoGenerationCollectorPolicy *policy =(TwoGenerationCollectorPolicy *)collector_policy();guarantee(policy->is_two_generation_policy(), "Illegal policy type");//校验Generation被正确的设置了DefNewGeneration* def_new_gen = (DefNewGeneration*) get_gen(0);assert(def_new_gen->kind() == Generation::DefNew ||def_new_gen->kind() == Generation::ParNew ||def_new_gen->kind() == Generation::ASParNew,"Wrong generation kind");Generation* old_gen = get_gen(1);assert(old_gen->kind() == Generation::ConcurrentMarkSweep ||old_gen->kind() == Generation::ASConcurrentMarkSweep ||old_gen->kind() == Generation::MarkSweepCompact,"Wrong generation kind");//初始化TwoGenerationCollectorPolicypolicy->initialize_size_policy(def_new_gen->eden()->capacity(),old_gen->capacity(),def_new_gen->from()->capacity());policy->initialize_gc_policy_counters();
}void SharedHeap::post_initialize() {CollectedHeap::post_initialize();ref_processing_init();
}void CollectedHeap::post_initialize() {collector_policy()->post_heap_initialize();
}void GenCollectedHeap::ref_processing_init() {SharedHeap::ref_processing_init();for (int i = 0; i < _n_gens; i++) {//初始化各代的ReferenceProcessor_gens[i]->ref_processor_init();}
}Generation* get_gen(int i) const {guarantee(i >= 0 && i < _n_gens, "Out of bounds");return _gens[i];}

其调用链如下:

3、do_collection

do_collection是GenCollectedHeap执行垃圾回收的核心方法,其底层核心就是各Genaration的collect方法,注意其实现如下:

void GenCollectedHeap::do_collection(bool  full,bool   clear_all_soft_refs,size_t size,bool   is_tlab,int    max_level) {bool prepared_for_verification = false;ResourceMark rm;DEBUG_ONLY(Thread* my_thread = Thread::current();)//校验处于安全点上assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint");//校验调用线程是VMThread 或者CMS Threadassert(my_thread->is_VM_thread() ||my_thread->is_ConcurrentGC_thread(),"incorrect thread type capability");//校验获取了Heap_lock锁assert(Heap_lock->is_locked(),"the requesting thread should have the Heap_lock");guarantee(!is_gc_active(), "collection is not reentrant");assert(max_level < n_gens(), "sanity check");//检查是否有线程处于JNI关键区,check_active_before_gc返回true表示有,则终止当前GC,等待线程退出//最后一个退出的线程会负责执行GCif (GC_locker::check_active_before_gc()) {return; // GC is disabled (e.g. JNI GetXXXCritical operation)}//是否需要清除软引用const bool do_clear_all_soft_refs = clear_all_soft_refs ||collector_policy()->should_clear_all_soft_refs();//ClearedAllSoftRefs通过析构函数设置CollectorPolicy的_all_soft_refs_clear属性ClearedAllSoftRefs casr(do_clear_all_soft_refs, collector_policy());//获取元空间已使用内存const size_t metadata_prev_used = MetaspaceAux::used_bytes();//打印GC的堆内存使用情况print_heap_before_gc();{//临时设置_is_gc_active为true,表示GC开始了FlagSetting fl(_is_gc_active, true);bool complete = full && (max_level == (n_gens()-1));const char* gc_cause_prefix = complete ? "Full GC" : "GC";TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);GCTraceTime t(GCCauseString(gc_cause_prefix, gc_cause()), PrintGCDetails, false, NULL, GCId::peek());//遍历各Generation执行GC准备工作gc_prologue(complete);//增加GC次数increment_total_collections(complete);//统计总的内存使用量size_t gch_prev_used = used();int starting_level = 0;if (full) {//找到老年代对应的levelfor (int i = max_level; i >= 0; i--) {if (_gens[i]->full_collects_younger_generations()) {starting_level = i;break;}}}bool must_restore_marks_for_biased_locking = false;int max_level_collected = starting_level;for (int i = starting_level; i <= max_level; i++) {if (_gens[i]->should_collect(full, size, is_tlab)) {//如果需要垃圾回收if (i == n_gens() - 1) {  // a major collection is to happen//如果是老年代if (!complete) {//increment_total_collections方法只有在complete为true时才会增加_total_full_collections计数//此处complete为false,但还是老年代的GC,所以增加计数increment_total_full_collections();}//根据参数配置dumppre_full_gc_dump(NULL);    // do any pre full gc dumps}GCTraceTime t1(_gens[i]->short_name(), PrintGCDetails, false, NULL, GCId::peek());TraceCollectorStats tcs(_gens[i]->counters());TraceMemoryManagerStats tmms(_gens[i]->kind(),gc_cause());size_t prev_used = _gens[i]->used();//增加计数_gens[i]->stat_record()->invocations++;_gens[i]->stat_record()->accumulated_time.start();//记录各Generation的Space的top指针,生产版本为空实现record_gen_tops_before_GC();if (PrintGC && Verbose) {gclog_or_tty->print("level=%d invoke=%d size=" SIZE_FORMAT,i,_gens[i]->stat_record()->invocations,size*HeapWordSize);}if (VerifyBeforeGC && i >= VerifyGCLevel &&total_collections() >= VerifyGCStartAt) {HandleMark hm;  // Discard invalid handles created during verificationif (!prepared_for_verification) {prepare_for_verify();prepared_for_verification = true;}Universe::verify(" VerifyBeforeGC:");}COMPILER2_PRESENT(DerivedPointerTable::clear());if (!must_restore_marks_for_biased_locking &&//DefNewGeneration返回false,ConcurrentMarkSweepGeneration采用父类默认实现返回true_gens[i]->performs_in_place_marking()) {must_restore_marks_for_biased_locking = true;//将各线程的持有偏向锁的oop的对象头保存起来BiasedLocking::preserve_marks();}// Do collection work{HandleMark hm;  // Discard invalid handles created during gcsave_marks();   // save marks for all gensReferenceProcessor* rp = _gens[i]->ref_processor();if (rp->discovery_is_atomic()) {rp->enable_discovery(true /*verify_disabled*/, true /*verify_no_refs*/);rp->setup_policy(do_clear_all_soft_refs);} else {//collect方法会调用enable_discovery方法}//执行垃圾回收_gens[i]->collect(full, do_clear_all_soft_refs, size, is_tlab);if (!rp->enqueuing_is_done()) {//enqueuing_is_done为false//将处理后剩余的References实例加入到pending-list中rp->enqueue_discovered_references();} else {//enqueuing_is_done为true,已经加入到pending-list中了,将其恢复成默认值rp->set_enqueuing_is_done(false);}rp->verify_no_references_recorded();}max_level_collected = i;// Determine if allocation request was met.if (size > 0) {if (!is_tlab || _gens[i]->supports_tlab_allocation()) {if (size*HeapWordSize <= _gens[i]->unsafe_max_alloc_nogc()) {size = 0;}}}COMPILER2_PRESENT(DerivedPointerTable::update_pointers());_gens[i]->stat_record()->accumulated_time.stop();//更新各Generation的GC统计信息update_gc_stats(i, full);if (VerifyAfterGC && i >= VerifyGCLevel &&total_collections() >= VerifyGCStartAt) {HandleMark hm;  // Discard invalid handles created during verificationUniverse::verify(" VerifyAfterGC:");}if (PrintGCDetails) {gclog_or_tty->print(":");_gens[i]->print_heap_change(prev_used);}}}//for循环结束//是否Full GCcomplete = complete || (max_level_collected == n_gens() - 1);if (complete) { // We did a "major" collection//根据配置dumppost_full_gc_dump(NULL);   // do any post full gc dumps}if (PrintGCDetails) {print_heap_change(gch_prev_used);if (complete) {MetaspaceAux::print_metaspace_change(metadata_prev_used);}}for (int j = max_level_collected; j >= 0; j -= 1) {//调整各Generation的容量_gens[j]->compute_new_size();}if (complete) {//删掉被卸载的ClassLoader实例及其相关元数据ClassLoaderDataGraph::purge();MetaspaceAux::verify_metrics();//重置元空间大小MetaspaceGC::compute_new_size();update_full_collections_completed();}//跟踪GC后的内存使用MemoryService::track_memory_usage();gc_epilogue(complete);if (must_restore_marks_for_biased_locking) {BiasedLocking::restore_marks();}}AdaptiveSizePolicy* sp = gen_policy()->size_policy();AdaptiveSizePolicyOutput(sp, total_collections());print_heap_after_gc();#ifdef TRACESPINNINGParallelTaskTerminator::print_termination_counts();
#endif
}//父类方法
bool is_gc_active() const { return _is_gc_active; }GCCause::Cause gc_cause() { return _gc_cause; }void GenCollectedHeap::gc_prologue(bool full) {assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer");always_do_update_barrier = false;//收集GC前的TLAB的统计数据CollectedHeap::accumulate_statistics_all_tlabs();//遍历各Generation执行ensure_parsabilityensure_parsability(true);   // retire TLABs//遍历各Generation执行gc_prologueGenGCPrologueClosure blk(full);generation_iterate(&blk, false);  // not old-to-young.
};void GenCollectedHeap::ensure_parsability(bool retire_tlabs) {CollectedHeap::ensure_parsability(retire_tlabs);GenEnsureParsabilityClosure ep_cl;generation_iterate(&ep_cl, false);
}//old_to_young决定了遍历的顺序,如果为true则先遍历老年代再遍历年轻代
void GenCollectedHeap::generation_iterate(GenClosure* cl,bool old_to_young) {if (old_to_young) {for (int i = _n_gens-1; i >= 0; i--) {cl->do_generation(_gens[i]);}} else {for (int i = 0; i < _n_gens; i++) {cl->do_generation(_gens[i]);}}
}class GenEnsureParsabilityClosure: public GenCollectedHeap::GenClosure {public:void do_generation(Generation* gen) {gen->ensure_parsability();}
};class GenGCPrologueClosure: public GenCollectedHeap::GenClosure {private:bool _full;public:void do_generation(Generation* gen) {gen->gc_prologue(_full);}GenGCPrologueClosure(bool full) : _full(full) {};
};void increment_total_collections(bool full = false) {//增加总的GC次数_total_collections++;if (full) {//增加Full GC的次数increment_total_full_collections();}}void increment_total_full_collections() { _total_full_collections++; }size_t GenCollectedHeap::used() const {size_t res = 0;//遍历各Generation累加内存使用量for (int i = 0; i < _n_gens; i++) {res += _gens[i]->used();}return res;
}//DefNewGeneration采用父类Generation的默认实现,返回false
//ConcurrentMarkSweepGeneration的实现如下
//UseCMSCompactAtFullCollection默认为true,表示FullGC时所使用Mark-Sweep-Compact算法
//CollectGen0First默认为false,表示是否在FullGC前收集年轻代virtual bool full_collects_younger_generations() const {return UseCMSCompactAtFullCollection && !CollectGen0First;}void CollectedHeap::pre_full_gc_dump(GCTimer* timer) {//HeapDumpBeforeFullGC默认为falseif (HeapDumpBeforeFullGC) {GCTraceTime tt("Heap Dump (before full gc): ", PrintGCDetails, false, timer, GCId::create());HeapDumper::dump_heap();}//PrintClassHistogramBeforeFullGC默认为falseif (PrintClassHistogramBeforeFullGC) {GCTraceTime tt("Class Histogram (before full gc): ", PrintGCDetails, true, timer, GCId::create());VM_GC_HeapInspection inspector(gclog_or_tty, false /* ! full gc */);inspector.doit();}
}#ifndef PRODUCT
class GenGCSaveTopsBeforeGCClosure: public GenCollectedHeap::GenClosure {private:public:void do_generation(Generation* gen) {gen->record_spaces_top();}
};void GenCollectedHeap::record_gen_tops_before_GC() {if (ZapUnusedHeapArea) {GenGCSaveTopsBeforeGCClosure blk;generation_iterate(&blk, false);  // not old-to-young.}
}
#endif void GenCollectedHeap::save_marks() {for (int i = 0; i < _n_gens; i++) {_gens[i]->save_marks();}
}void update_gc_stats(int current_level, bool full) {for (int i = 0; i < _n_gens; i++) {_gens[i]->update_gc_stats(current_level, full);}}void CollectedHeap::post_full_gc_dump(GCTimer* timer) {//HeapDumpAfterFullGC默认为falseif (HeapDumpAfterFullGC) {GCTraceTime tt("Heap Dump (after full gc): ", PrintGCDetails, false, timer, GCId::create());HeapDumper::dump_heap();}//PrintClassHistogramAfterFullGC默认为falseif (PrintClassHistogramAfterFullGC) {GCTraceTime tt("Class Histogram (after full gc): ", PrintGCDetails, true, timer, GCId::create());VM_GC_HeapInspection inspector(gclog_or_tty, false /* ! full gc */);inspector.doit();}
}unsigned int GenCollectedHeap::update_full_collections_completed() {MonitorLockerEx ml(FullGCCount_lock, Mutex::_no_safepoint_check_flag);assert(_full_collections_completed <= _total_full_collections,"Can't complete more collections than were started");//获取锁FullGCCount_lock,更新_full_collections_completed属性_full_collections_completed = _total_full_collections;ml.notify_all();return _full_collections_completed;
}void GenCollectedHeap::gc_epilogue(bool full) {
#ifdef COMPILER2assert(DerivedPointerTable::is_empty(), "derived pointer present");size_t actual_gap = pointer_delta((HeapWord*) (max_uintx-3), *(end_addr()));guarantee(actual_gap > (size_t)FastAllocateSizeLimit, "inline allocation wraps");
#endif /* COMPILER2 *///重新计算各线程的TLAB的分配大小resize_all_tlabs();//遍历各Generation执行gc_epilogue方法GenGCEpilogueClosure blk(full);generation_iterate(&blk, false);  // not old-to-young.//CleanChunkPoolAsync默认为falseif (!CleanChunkPoolAsync) {//清理ChunkPoolChunk::clean_chunk_pool();}//更新计数器MetaspaceCounters::update_performance_counters();CompressedClassSpaceCounters::update_performance_counters();always_do_update_barrier = UseConcMarkSweepGC;
};void CollectedHeap::resize_all_tlabs() {if (UseTLAB) {assert(SafepointSynchronize::is_at_safepoint() ||!is_init_completed(),"should only resize tlabs at safepoint");//重新计算各线程的TLAB的大小ThreadLocalAllocBuffer::resize_all_tlabs();}
}class GenGCEpilogueClosure: public GenCollectedHeap::GenClosure {private:bool _full;public:void do_generation(Generation* gen) {gen->gc_epilogue(_full);}GenGCEpilogueClosure(bool full) : _full(full) {};
};

上述代码中的ClearedAllSoftRefs的定义如下:

FlagSetting的定义如下:

该方法的调用链如下:

4、do_full_collection

do_full_collection有两个重载版本,用来执行年轻代或者老年代的“full gc”,即底层调用do_collection方法时,full参数是true,其实现如下:

void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs) {do_full_collection(clear_all_soft_refs, _n_gens - 1);
}void GenCollectedHeap::do_full_collection(bool clear_all_soft_refs,int max_level) {int local_max_level;if (!incremental_collection_will_fail(false /* don't consult_young */) && //此时返回false说明老年代空间是足够的gc_cause() == GCCause::_gc_locker) { //如果是最后一个从JNI关键区退出的线程触发的GC,满足这两个条件则只执行年轻代的垃圾回收local_max_level = 0;} else {local_max_level = max_level;}do_collection(true                 /* full */,clear_all_soft_refs  /* clear_all_soft_refs */,0                    /* size */,false                /* is_tlab */,local_max_level      /* max_level */);//如果只执行年轻代的GC,但是因为老年满了导致GC失败,则重试if (local_max_level == 0 && gc_cause() == GCCause::_gc_locker &&incremental_collection_will_fail(false /* don't consult_young */)) {if (PrintGCDetails) {gclog_or_tty->print_cr("GC locker: Trying a full collection ""because scavenge failed");}//会执行老年代和年轻代的GCdo_collection(true                 /* full */,clear_all_soft_refs  /* clear_all_soft_refs */,0                    /* size */,false                /* is_tlab */,n_gens() - 1         /* max_level */);}
}bool incremental_collection_will_fail(bool consult_young) {assert(heap()->collector_policy()->is_two_generation_policy(),"the following definition may not be suitable for an n(>2)-generation system");return incremental_collection_failed() ||(consult_young && !get_gen(0)->collection_attempt_is_safe());}//当老年代空间不足以promote,年轻代执行GC前调用collection_attempt_is_safe方法返回false,就会将_incremental_collection_failed属性置为false
bool incremental_collection_failed() const {return _incremental_collection_failed;}

_incremental_collection_failed属性通过set_incremental_collection_failed方法设置为true,该方法的调用链如下:

都是在collection_attempt_is_safe方法返回false,即利用老年代执行promote时因为老年代内存不足可能会失败时调用的。

GCCause::_gc_locker的调用链如下:

其中只有GC_locker::jni_unlock方法不是判断GC的原因是否是_gc_locker,如下:

该方法就是用于在最后一个线程从JNI关键区退出后负责触发GC。

do_full_collection方法的调用链如下:

5、collect

collect方法是对JVM外部如JNI接口使用的触发垃圾回收的方法,其调用链如下:

上述调用场景都是基于JNI接口的调用,其中JVM_GC就是System.gc()方法的底层实现,其实现如下:

collect方法的实现如下:

void GenCollectedHeap::collect(GCCause::Cause cause) {if (should_do_concurrent_full_gc(cause)) {
#if INCLUDE_ALL_GCS// mostly concurrent full collectioncollect_mostly_concurrent(cause);
#else  // INCLUDE_ALL_GCSShouldNotReachHere();
#endif // INCLUDE_ALL_GCS} else if (cause == GCCause::_wb_young_gc) {// minor collection for WhiteBox APIcollect(cause, 0);} else {// Stop-the-world full collectioncollect(cause, n_gens() - 1);}
}bool GenCollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) {
//UseConcMarkSweepGC表示使用CMS GC算法
//GCLockerInvokesConcurrent的默认值为false
//ExplicitGCInvokesConcurrent的默认值也是falsereturn UseConcMarkSweepGC &&((cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) ||(cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent));
}void GenCollectedHeap::collect_mostly_concurrent(GCCause::Cause cause) {assert(!Heap_lock->owned_by_self(), "Should not own Heap_lock");MutexLocker ml(Heap_lock);// Read the GC counts while holding the Heap_lockunsigned int full_gc_count_before = total_full_collections();unsigned int gc_count_before      = total_collections();{MutexUnlocker mu(Heap_lock);//底层调用do_full_collectionVM_GenCollectFullConcurrent op(gc_count_before, full_gc_count_before, cause);VMThread::execute(&op);}
}void GenCollectedHeap::collect(GCCause::Cause cause, int max_level) {// The caller doesn't have the Heap_lockassert(!Heap_lock->owned_by_self(), "this thread should not own the Heap_lock");MutexLocker ml(Heap_lock);collect_locked(cause, max_level);
}void GenCollectedHeap::collect_locked(GCCause::Cause cause, int max_level) {// Read the GC count while holding the Heap_lockunsigned int gc_count_before      = total_collections();unsigned int full_gc_count_before = total_full_collections();{//获取Heap_lock锁MutexUnlocker mu(Heap_lock);  // give up heap lock, execute gets it back//底层还是调用do_full_collectionVM_GenCollectFull op(gc_count_before, full_gc_count_before,cause, max_level);VMThread::execute(&op);}
}

6、VM_GenCollectFullConcurrent / VM_GenCollectFull

VM_GenCollectFull比较简单,就是调用do_full_collection方法;VM_GenCollectFullConcurrent要复杂点,年轻代通过do_full_collection方法执行GC,老年代通过触发CMSThread执行GC,即异步完成GC,其实现如下:

VM_GenCollectFull(uint gc_count_before,uint full_gc_count_before,GCCause::Cause gc_cause,int max_level): VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true /* full */),_max_level(max_level) { }void VM_GenCollectFull::doit() {SvcGCMarker sgcm(SvcGCMarker::FULL);GenCollectedHeap* gch = GenCollectedHeap::heap();GCCauseSetter gccs(gch, _gc_cause);gch->do_full_collection(gch->must_clear_all_soft_refs(), _max_level);
}VM_GenCollectFullConcurrent(uint gc_count_before,uint full_gc_count_before,GCCause::Cause gc_cause): VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true /* full */),_disabled_icms(false){assert(FullGCCount_lock != NULL, "Error");assert(UseAsyncConcMarkSweepGC, "Else will hang caller");}//判断是否需要在安全点上执行
bool VM_GenCollectFullConcurrent::evaluate_at_safepoint() const {Thread* thr = Thread::current();assert(thr != NULL, "Unexpected tid");if (!thr->is_Java_thread()) {//如果是VMThread执行的assert(thr->is_VM_thread(), "Expected to be evaluated by VM thread");GenCollectedHeap* gch = GenCollectedHeap::heap();if (_gc_count_before != gch->total_collections()) {//如果已经完成了一次Young GCassert(_gc_count_before < gch->total_collections(),"total_collections() should be monotnically increasing");return false;  // no need for foreground young gc}}//如果是JavaThread调用的,如System.gc()方法return true;       // may still need foreground young gc
}void VM_GenCollectFullConcurrent::doit() {assert(Thread::current()->is_VM_thread(), "Should be VM thread");assert(GCLockerInvokesConcurrent || ExplicitGCInvokesConcurrent, "Unexpected");GenCollectedHeap* gch = GenCollectedHeap::heap();if (_gc_count_before == gch->total_collections()) {//GC的次数没有变说明未执行young gcassert(SafepointSynchronize::is_at_safepoint(),"We can only be executing this arm of if at a safepoint");GCCauseSetter gccs(gch, _gc_cause);//执行年轻代的垃圾回收gch->do_full_collection(gch->must_clear_all_soft_refs(),0 /* collect only youngest gen */);} // Else no need for a foreground young gcassert((_gc_count_before < gch->total_collections()) || //执行过GC了(GC_locker::is_active()   && (_gc_count_before == gch->total_collections())), //因为有线程处于JNI关键区,GC被中止了"total_collections() should be monotonically increasing");//获取锁FullGCCount_lockMutexLockerEx x(FullGCCount_lock, Mutex::_no_safepoint_check_flag);assert(_full_gc_count_before <= gch->total_full_collections(), "Error");if (gch->total_full_collections() == _full_gc_count_before) {//total_full_collections未变,说明老年代的GC未执行//禁用icmsCMSCollector::disable_icms();_disabled_icms = true;//唤醒在icms_wait()上等待的CMS ThreadCMSCollector::start_icms();//推动CMS Thread执行一次老年代的GCCMSCollector::request_full_gc(_full_gc_count_before, _gc_cause);} else {//说明已经执行过一次老年代GC了,不用再执行assert(_full_gc_count_before < gch->total_full_collections(), "Error");FullGCCount_lock->notify_all();  // Inform the Java thread its work is done}
}//GC结束后调用
void VM_GenCollectFullConcurrent::doit_epilogue() {Thread* thr = Thread::current();assert(thr->is_Java_thread(), "just checking");JavaThread* jt = (JavaThread*)thr;//释放锁Heap_lock->unlock();release_and_notify_pending_list_lock();GenCollectedHeap* gch = GenCollectedHeap::heap();if (_gc_cause != GCCause::_gc_locker &&gch->total_full_collections_completed() <= _full_gc_count_before) {//正常只有调用System.gc()时会走此方法assert(_gc_cause == GCCause::_java_lang_system_gc,"the only way to get here if this was a System.gc()-induced GC");assert(ExplicitGCInvokesConcurrent, "Error");//调整线程状态由in vm到in nativeeThreadToNativeFromVM native(jt);//获取锁MutexLockerExMutexLockerEx ml(FullGCCount_lock, Mutex::_no_safepoint_check_flag);while (gch->total_full_collections_completed() <= _full_gc_count_before) {//还是小于等于,说明GC未完成,在FullGCCount_lock上等待直到total_full_collections_completed大于_full_gc_count_before//即GC结束FullGCCount_lock->wait(Mutex::_no_safepoint_check_flag);}}if (_disabled_icms) {//重新开启icmsCMSCollector::enable_icms();}
}bool GenCollectedHeap::must_clear_all_soft_refs() {return _gc_cause == GCCause::_last_ditch_collection;
}void CMSCollector::request_full_gc(unsigned int full_gc_count, GCCause::Cause cause) {GenCollectedHeap* gch = GenCollectedHeap::heap();unsigned int gc_count = gch->total_full_collections();if (gc_count == full_gc_count) {MutexLockerEx y(CGC_lock, Mutex::_no_safepoint_check_flag);_full_gc_requested = true;_full_gc_cause = cause;CGC_lock->notify();   //唤醒CMS Thread,该线程检查_full_gc_requested为true会触发一次老年代的GC} else {assert(gc_count > full_gc_count, "Error: causal loop");}
}unsigned int total_full_collections_completed() {assert(_full_collections_completed <= _total_full_collections,"Can't complete more collections than were started");return _full_collections_completed;}

上述代码中的ThreadToNativeFromVM用于将当前线程的状态从in vm调整成in native,其实现如下:

7、gen_process_roots / gen_process_weak_roots

gen_process_roots用于遍历处理ClassLoaderDataGraph,Threads,Universe等组件中包含的oop,将这些oop作为根节点遍历其所引用的其他oop,根据参数还能遍历年轻代和老年代中的所有oop,遍历脏的卡表项对应的内存区域中包含的oop。gen_process_weak_roots用于遍历JNI弱引用和Reference弱引用实例。

void GenCollectedHeap::gen_process_weak_roots(OopClosure* root_closure) {//遍历JNI弱引用JNIHandles::weak_oops_do(root_closure);for (int i = 0; i < _n_gens; i++) {//遍历所有的Reference实例_gens[i]->ref_processor()->weak_oops_do(root_closure);}
}void GenCollectedHeap::gen_process_roots(int level,bool younger_gens_as_roots,bool activate_scope,ScanningOption so,bool only_strong_roots,OopsInGenClosure* not_older_gens,OopsInGenClosure* older_gens,CLDClosure* cld_closure) {const bool is_adjust_phase = !only_strong_roots && !younger_gens_as_roots;bool is_moving_collection = false;if (level == 0 || is_adjust_phase) {//is_moving_collection表示垃圾回收过程中是否会移动对象is_moving_collection = true;}//is_moving_collection实际对应_fix_relocations属性,如果为true,则遍历nmethod完后,会调用
//其fix_oop_relocations方法用于让nmethod中的oop指向对象移动后的地址MarkingCodeBlobClosure mark_code_closure(not_older_gens, is_moving_collection);//weak_roots主要用于遍历StringTable中保存的String对象和SystemDictionary中保存的ProtectionDomain对象,这些对象如果不遍历且不被其他存活对象引用则会被回收掉OopsInGenClosure* weak_roots = only_strong_roots ? NULL : not_older_gens;//weak_cld_closure用来遍历keep_live属性为false的ClassLoaderData,同上,如果不遍历则会被回收掉CLDClosure* weak_cld_closure = only_strong_roots ? NULL : cld_closure;//处理ClassLoaderDataGraph,Threads,Universe等组件中包含的oop,这些都作为根节点process_roots(activate_scope, so,not_older_gens, weak_roots,cld_closure, weak_cld_closure,&mark_code_closure);if (younger_gens_as_roots) {//younger_gens_as_roots为true,表示需要遍历年轻代中的所有对象,将其作为根节点//is_task_claimed返回false表示这个任务还未执行if (!_process_strong_tasks->is_task_claimed(GCH_PS_younger_gens)) {//因为是i小于level,所以对年轻代而言,即使younger_gens_as_roots为true,也不会执行//只有老年代,level=1时才会进入此分支for (int i = 0; i < level; i++) {not_older_gens->set_generation(_gens[i]);_gens[i]->oop_iterate(not_older_gens);}not_older_gens->reset_generation();}}//level最低是0,即年轻代GC会调用老年代的younger_refs_iterate方法,如果level是1则不做任何处理,即老年代GC不会执行此逻辑for (int i = level+1; i < _n_gens; i++) {older_gens->set_generation(_gens[i]);//younger_refs_iterate支持并行遍历,注意年轻代的该方法是一个空实现rem_set()->younger_refs_iterate(_gens[i], older_gens);older_gens->reset_generation();}//标识当前线程执行完成_process_strong_tasks->all_tasks_completed();
}void GenCollectedHeap::process_roots(bool activate_scope,ScanningOption so,OopClosure* strong_roots,OopClosure* weak_roots,CLDClosure* strong_cld_closure,CLDClosure* weak_cld_closure,CodeBlobToOopClosure* code_roots) {//修改SharedHeap的_strong_roots_parity属性                                  StrongRootsScope srs(this, activate_scope);// General roots.assert(_strong_roots_parity != 0, "must have called prologue code");assert(code_roots != NULL, "code root closure should always be set");//如果这个任务还未执行if (!_process_strong_tasks->is_task_claimed(GCH_PS_ClassLoaderDataGraph_oops_do)) {//遍历所有的ClassLoaderData,如果ClassLoaderData的keep_alive为true则使用strong_cld_closure处理,否则使用weak_cld_closureClassLoaderDataGraph::roots_cld_do(strong_cld_closure, weak_cld_closure);}CLDClosure* roots_from_clds_p = (strong_cld_closure != weak_cld_closure) ? strong_cld_closure : NULL;//so & SO_AllCodeCache为true即so等于SO_AllCodeCache或者SO_ScavengeCodeCacheCodeBlobToOopClosure* roots_from_code_p = (so & SO_AllCodeCache) ? NULL : code_roots;//遍历所有JavaThread和VMThread中包含的oop,包含通过JNI创建的oop和栈上的oopThreads::possibly_parallel_oops_do(strong_roots, roots_from_clds_p, roots_from_code_p);if (!_process_strong_tasks->is_task_claimed(GCH_PS_Universe_oops_do)) {//遍历Universe中包含的oopUniverse::oops_do(strong_roots);}// Global (strong) JNI handlesif (!_process_strong_tasks->is_task_claimed(GCH_PS_JNIHandles_oops_do)) {//遍历JNI全局引用中的oopJNIHandles::oops_do(strong_roots);}if (!_process_strong_tasks->is_task_claimed(GCH_PS_ObjectSynchronizer_oops_do)) {//遍历ObjectSynchronizer即synchronize关键字的实现中包含的oop,主要是锁对象ObjectSynchronizer::oops_do(strong_roots);}if (!_process_strong_tasks->is_task_claimed(GCH_PS_FlatProfiler_oops_do)) {FlatProfiler::oops_do(strong_roots);}if (!_process_strong_tasks->is_task_claimed(GCH_PS_Management_oops_do)) {//遍历MemoryService和ThreadService中的oopManagement::oops_do(strong_roots);}if (!_process_strong_tasks->is_task_claimed(GCH_PS_jvmti_oops_do)) {JvmtiExport::oops_do(strong_roots);}if (!_process_strong_tasks->is_task_claimed(GCH_PS_SystemDictionary_oops_do)) {//遍历SystemDictionary系统字典中的oopSystemDictionary::roots_oops_do(strong_roots, weak_roots);}//所有线程都要执行一遍StringTable的oop遍历if (weak_roots != NULL) {if (CollectedHeap::use_parallel_gc_threads()) {StringTable::possibly_parallel_oops_do(weak_roots);} else {StringTable::oops_do(weak_roots);}}if (!_process_strong_tasks->is_task_claimed(GCH_PS_CodeCache_oops_do)) {//SO_AllCodeCache是包含SO_ScavengeCodeCache的,所以如果是SO_ScavengeCodeCache
//也会执行此逻辑if (so & SO_ScavengeCodeCache) {assert(code_roots != NULL, "must supply closure for code cache");//遍历nmethodsCodeCache::scavenge_root_nmethods_do(code_roots);}if (so & SO_AllCodeCache) {assert(code_roots != NULL, "must supply closure for code cache");// 遍历整个CodeBlobCodeCache::blobs_do(code_roots);}}
}void CardTableRS::younger_refs_iterate(Generation* g,OopsInGenClosure* blk) {_last_cur_val_in_gen[g->level()+1] = cur_youngergen_card_val();//年轻代该方法是空实现,老年代下底层是调用CardTableRS::younger_refs_in_space_iterate方法来遍历脏的卡表项//将脏的卡表项对应的内存区域中包含的oop作为根节点g->younger_refs_iterate(blk);
}

StrongRootsScope用来改变SharedHeap的_strong_roots_parity属性,其实现如下:

其调用链如下:

CardTableRS::younger_refs_iterate方法相关实现可以参考《Hotspot 垃圾回收之BarrierSet(三) 源码解析》、《Hotspot 垃圾回收之ConcurrentMarkSweepGeneration(三) 源码解析》和《Hotspot 垃圾回收之CompactibleFreeListSpace(三) 源码解析》,整体实现比较复杂。

8、save_marks / oop_since_save_marks_iterate / no_allocs_since_save_marks

oop_since_save_marks_iterate并不是简单的调用底层Generation的oop_since_save_marks_iterate方法,而是有特殊逻辑在里面,其定义同样是通过宏实现的,如下:

void GenCollectedHeap::save_marks() {for (int i = 0; i < _n_gens; i++) {_gens[i]->save_marks();}
}#define GCH_SINCE_SAVE_MARKS_ITERATE_DEFN(OopClosureType, nv_suffix)    \
void GenCollectedHeap::                                                 \
oop_since_save_marks_iterate(int level,                                 \OopClosureType* cur,                       \OopClosureType* older) {                   \//先遍历指定level的_gens[level]->oop_since_save_marks_iterate##nv_suffix(cur);           \//再遍历老年代,如果level本身就是1则不做处理for (int i = level+1; i < n_gens(); i++) {                            \_gens[i]->oop_since_save_marks_iterate##nv_suffix(older);           \}                                                                     \
}ALL_SINCE_SAVE_MARKS_CLOSURES(GCH_SINCE_SAVE_MARKS_ITERATE_DEFN)//只要有一个Generation的no_allocs_since_save_marks返回false,则no_allocs_since_save_marks同样返回false
bool GenCollectedHeap::no_allocs_since_save_marks(int level) {for (int i = level; i < _n_gens; i++) {if (!_gens[i]->no_allocs_since_save_marks()) return false;}return true;
}

各方法的调用链如下:

即如果是年轻代调用,则会处理年轻代和老年代,如果是老年代调用,则只处理老年代。年轻代调用oop_since_save_marks_iterate是遍历saved_mark_word到top之间的对象,主要是年轻代并行遍历和老年代通过CMSThread遍历时使用,如果是单线程的年轻代遍历则不做任何处理,因为此时saved_mark_word就是top,老年代是遍历所有被promoted的对象。

9、ensure_parsability

GenCollectedHeap改写了父类的实现,在父类的基础上增加了各各Generation的ensure_parsability方法的调用,但是CMS下年轻代和老年代都是空实现,父类方法的实现可以参考《Hotspot 垃圾回收之BarrierSet(三) 源码解析》。

void GenCollectedHeap::ensure_parsability(bool retire_tlabs) {//调用父类实现,父类实现会遍历所有的JavaThread,让其TLAB被填充或者退休,不再用于分配对象,同时将上一次本地代码创建的对象对应的卡表项置为脏的CollectedHeap::ensure_parsability(retire_tlabs);//调用各Generation的ensure_parsability方法,CMS下年轻代和老年代都是空实现GenEnsureParsabilityClosure ep_cl;generation_iterate(&ep_cl, false);
}class GenEnsureParsabilityClosure: public GenCollectedHeap::GenClosure {public:void do_generation(Generation* gen) {gen->ensure_parsability();}
};

Hotspot 垃圾回收之GenCollectedHeap 源码解析相关推荐

  1. Hotspot 垃圾回收之VM_Operation 源码解析

    目录 一.VM_Operation ​二.VMThread 1.定义 2.create / destroy 3.run / wait_for_vm_thread_exit 4.loop 5.VMThr ...

  2. Hotspot 对象引用Reference和Finalizer 源码解析

    目录 一.Reference 1.SoftReference / WeakReference / PhantomReference 2.定义 3.ReferenceHandler 4.Cleaner ...

  3. android进阶篇02、RecyclerView回收复用机制源码解析,h5移动端开发进行定位

    public void removeAndRecycleViewAt(int index, @NonNull Recycler recycler) { final View view = getChi ...

  4. Hotspot 垃圾回收之oop_iterate(二) 源码解析

    目录 1.java.lang.Class 1.1.Class实例中oop_size.klass等属性是哪来的? 1.2._offset_of_static_fields 1.3 为什么从_offset ...

  5. Hotspot 垃圾回收之ReferenceProcessor(二) 源码解析

    目录 1.process_discovered_reflist 2.process_phaseJNI 3.process_discovered_references 4.preclean_discov ...

  6. Hotspot 重量级锁ObjectMonitor(一) 源码解析

    目录 1.定义 2.TrySpin_VaryDuration 3.ObjectWaiter 4.EnterI 5.JavaThreadBlockedOnMonitorEnterState / OSTh ...

  7. Python 的垃圾回收回收机制(源码)

    python内存管理及垃圾回收 1. 引用计数器 1.1 环状双向连表 refchain 在python程序中创建的任何对象都会放在refchain链表中,并且可以通过这个对象访问到上一个和下一个对象 ...

  8. Hotspot 重量级锁ObjectMonitor(二) 源码解析

    目录 1.AddWaiter / DequeueWaiter /DequeueSpecificWaiter 2.wait 3.notify 4.notifyAll 5.exit 6.try_enter ...

  9. Glide 4.9源码解析-缓存策略

    本文Glide源码基于4.9,版本下载地址如下:Glide 4.9 前言 在分析了Glide的图片加载流程后,更加发觉到Glide的强大,于是这篇文章将继续深入分析Glide的缓存策略.不过今天的文章 ...

最新文章

  1. 参数估计_数据分析|统计之一个总体参数估计(附代码)
  2. 网络营销——网站权重并不是判断网站营销水平的唯一标准
  3. BFE Ingress Controller正式发布!
  4. python基础的学习
  5. 数据结构中的7种排序算法
  6. 阶段3 2.Spring_03.Spring的 IOC 和 DI_10 构造函数注入
  7. windows7 XP 如何安装netbeui协议
  8. 欧姆龙nb触摸屏通信_313C和欧姆龙NB触摸屏怎么通讯
  9. 在北京买车可以上外地牌照吗
  10. 【Practical】线性空间
  11. 借助花生壳使用公网远程连接Jetson nano
  12. 学习计算机嵌入式的笔记汇总
  13. 西邮计算机组成原理期末考试,计算机组成原理小抄西邮版.doc
  14. python爬取电影并下载
  15. (C语言)的全称是什么?
  16. Python爬取携程酒店信息
  17. 中文字符 与 十六进制Unicode编码 相互转换
  18. JbdcTemplate操作数据库
  19. 2019榆次初三计算机考试时间,2019晋中中考总分是多少 录取分数线是多少
  20. python与数据处理课后答案_python数据处理与科学计算_课程2020最新章节测试网课课后答案...

热门文章

  1. 南瓜科学好奇盒子上新 打造新时代玩具总动员
  2. 百度搜索中台海量数据管理的云原生和智能化实践
  3. LabVIEW练习5
  4. 吸引那么多人参与,华为生态伙伴精英赛有什么魅力?
  5. 银行卡秒变公交卡,什么鬼?
  6. java 2048游戏_JAVA2048游戏 本课程设计是基于java语言的2048小游戏设计 联合开发网 - pudn.com...
  7. Hopscotch(思维)
  8. 详述微信内推广H5和棋牌类APP如何做好域名防封处理
  9. C++中的COORD,SetConsoleCursorPosition(),_kbhit(),_getch()函数
  10. TRIZ理论学习的思考