full gc是g1正常的gc cycle回收无力的情况下进行的,相对来说比较简单
主要入口代码在 g1CollectedHeap.cpp
do_full_collection
bool G1CollectedHeap::do_full_collection(bool explicit_gc,
bool clear_all_soft_refs,
bool do_maximum_compaction) {
assert_at_safepoint_on_vm_thread();
//检查jni lock
if (GCLocker::check_active_before_gc()) {
// Full GC was not completed.
return false;
}
//判断系统是否需要回收所有软连接,主要看空间紧急程度
const bool do_clear_all_soft_refs = clear_all_soft_refs ||
soft_ref_policy()->should_clear_all_soft_refs();
G1FullCollector collector(this, explicit_gc, do_clear_all_soft_refs, do_maximum_compaction);
GCTraceTime(Info, gc) tm("Pause Full", NULL, gc_cause(), true);
//准备阶段,主要是打印日志,停止cycle,停止并发标记,关闭活跃区域等
collector.prepare_collection();
collector.collect();
//清理标记状态,记录full gc结束日志等
collector.complete_collection();
// Full collection was successfully completed.
return true;
}
full gc分为四个阶段,对应四个task,看对应的work方法即可
G1FullGCMarkTask,G1FullGCPrepareTask,G1FullGCAdjustTask,G1FullGCCompactTask
void G1FullCollector::collect() {
//标记,<<深入理解jvm虚拟机>>书上没看到这种full gc标记过程
phase1_mark_live_objects();
verify_after_marking();
// Don't add any more derived pointers during later phases
//栈上的派生类指针表进行关闭
deactivate_derived_pointers();
//压缩准备,判断region空间是否需要压缩,存入一个队列compaction queue
phase2_prepare_compaction();
//指针调整,新region地址更新
phase3_adjust_pointers();
//压缩region,处理第二步的东西
phase4_do_compaction();
}
phase1_mark_live_objects
使用到了gc线程来进行的标记,就是初始化g1heap出现的_worker,线程中再使用G1FullGCMarker的线程
void G1FullCollector::phase1_mark_live_objects() {
// Recursively traverse all live objects and mark them.
GCTraceTime(Info, gc, phases) info("Phase 1: Mark live objects", scope()->timer());
{
// Do the actual marking.
//标记,不是并发的,在prepare阶段concurrent_cycle_abort关了
G1FullGCMarkTask marking_task(this);
//实际调用就是task的work方法
run_task(&marking_task);
}
{ //引用处理器ReferenceProcessor,一种是并发的_ref_processor_cm还有就是这里的_ref_processor_stw
//stw的开启会关闭cm的,并且开启单单线程,full gc中发现任何引用都会记录进来
uint old_active_mt_degree = reference_processor()->num_queues();
reference_processor()->set_active_mt_degree(workers());
GCTraceTime(Debug, gc, phases) debug("Phase 1: Reference Processing", scope()->timer());
// Process reference objects found during marking.
//标记过程中出现的引用处理
ReferenceProcessorPhaseTimes pt(scope()->timer(), reference_processor()->max_num_queues());
G1FullGCRefProcProxyTask task(*this, reference_processor()->max_num_queues());
//处理引用,按照软强弱虚的顺序处理
const ReferenceProcessorStats& stats = reference_processor()->process_discovered_references(task, pt);
scope()->tracer()->report_gc_reference_stats(stats);
pt.print_all_references();
assert(marker(0)->oop_stack()->is_empty(), "Should be no oops on the stack");
reference_processor()->set_active_mt_degree(old_active_mt_degree);
}
// Weak oops cleanup.
// 对象只有一个弱引用的话就要被回收
// 这里处理会开多个线程,将弱引用地址所指的对象循环查看,不是空的且不是存活的对象就释放引用
{
GCTraceTime(Debug, gc, phases) debug("Phase 1: Weak Processing", scope()->timer());
WeakProcessor::weak_oops_do(_heap->workers(), &_is_alive, &do_nothing_cl, 1);
}
// Class unloading and cleanup.
// classloader卸载class,要从符号表移除
if (ClassUnloading) {
GCTraceTime(Debug, gc, phases) debug("Phase 1: Class Unloading and Cleanup", scope()->timer());
// Unload classes and purge the SystemDictionary.
bool purged_class = SystemDictionary::do_unloading(scope()->timer());
_heap->complete_cleaning(&_is_alive, purged_class);
}
scope()->tracer()->report_object_count_after_gc(&_is_alive);
}
多线程处理标记,GcRoots,注意这里不是说传统意义的多线程来处理,而是我们需要对每个线程进行处理
void G1FullGCMarkTask::work(uint worker_id) {
Ticks start = Ticks::now();
ResourceMark rm;
G1FullGCMarker* marker = collector()->marker(worker_id);
MarkingCodeBlobClosure code_closure(marker->mark_closure(), !CodeBlobToOopClosure::FixRelocations);
//ClassUnloading默认为true
if (ClassUnloading) {
//处理gcRoots
_root_processor.process_strong_roots(marker->mark_closure(),
marker->cld_closure(),
&code_closure);
} else {
_root_processor.process_all_roots(marker->mark_closure(),
marker->cld_closure(),
&code_closure);
}
// Mark stack is populated, now process and drain it.
//之前遍历roots生成的stack进行抽取处理
//通过mark word将存活的对象记录到_mark_stats_cache
marker->complete_marking(collector()->oop_queue_set(), collector()->array_queue_set(), &_terminator);
marker->flush_mark_stats_cache();
// This is the point where the entire marking should have completed.
assert(marker->oop_stack()->is_empty(), "Marking should have completed");
assert(marker->objarray_stack()->is_empty(), "Array marking should have completed");
log_task("Marking task", worker_id, start);
}
process_strong_roots标记gcRoots
void G1RootProcessor::process_strong_roots(OopClosure* oops,
CLDClosure* clds,
CodeBlobClosure* blobs) {
StrongRootsClosures closures(oops, clds, blobs);
//1.清除本地方法nmethod线程栈外的对象
//2.重新映射对象
//3.标记存活对象
process_java_roots(&closures, NULL, 0);
process_vm_roots(&closures, NULL, 0);
// CodeCache is already processed in java roots
// refProcessor is not needed since we are inside a safe point
_process_strong_tasks.all_tasks_claimed(G1RP_PS_CodeCache_oops_do,
G1RP_PS_refProcessor_oops_do);
}
先看StrongRootsClosures closures(oops, clds, blobs);
这里三个参数的类型为G1MarkAndPushClosure,CLDToOopClosure,MarkingCodeBlobClosure
对应获取方法strong_oops(),strong_clds(),strong_codeblobs()
对应的root为java引用,类加载器对象,方法对象
实际运行的就是这些closure
complete_marking 处理前一步从强引用,类加载器,方法区获得的gcRoots对象
void G1FullGCMarker::complete_marking(OopQueueSet* oop_stacks,
ObjArrayTaskQueueSet* array_stacks,
TaskTerminator* terminator) {
do {
//处理标记
drain_stack();
ObjArrayTask steal_array;
//从其他worker线程取任务继续处理
if (array_stacks->steal(_worker_id, steal_array)) {
follow_array_chunk(objArrayOop(steal_array.obj()), steal_array.index());
} else {
oop steal_oop;
if (oop_stacks->steal(_worker_id, steal_oop)) {
follow_object(steal_oop);
}
}
} while (!is_empty() || !terminator->offer_termination());
}
//处理
void G1FullGCMarker::drain_stack() {
do {
oop obj;
//从之前gcroots标记的_oop_stack获取对象到obj
while (pop_object(obj)) {
assert(_bitmap->is_marked(obj), "must be marked");
//标记成员,也就是可达对象,mark_push后再while循环,不可达的对象最后会被回收
follow_object(obj);
}
// Process ObjArrays one at a time to avoid marking stack bloat.
ObjArrayTask task;
if (pop_objarray(task)) {
follow_array_chunk(objArrayOop(task.obj()), task.index());
}
} while (!is_empty());
}
phase2_prepare_compaction
直接看G1FullGCPrepareTask核心代码
bool G1FullGCPrepareTask::G1CalculatePointersClosure::do_heap_region(HeapRegion* hr) {
bool force_not_compacted = false;
if (should_compact(hr)) {
//首先通过hrm region管理器查看对应region是否已经pinned(归档或者是大对象),再检查region压缩的临界值
assert(!hr->is_humongous(), "moving humongous objects not supported.");
//到达临界值没有锁定的region放入队列
prepare_for_compaction(hr);
} else {
// There is no need to iterate and forward objects in pinned regions ie.
// prepare them for compaction. The adjust pointers phase will skip
// work for them.
assert(hr->containing_set() == nullptr, "already cleared by PrepareRegionsClosure");
if (hr->is_humongous()) {
oop obj = cast_to_oop(hr->humongous_start_region()->bottom());
//大对象检查是否标记,不在标记的进行回收且放入回收队列
if (!_bitmap->is_marked(obj)) {
free_pinned_region<true>(hr);
}
} else if (hr->is_open_archive()) {
bool is_empty = _collector->live_words(hr->hrm_index()) == 0;
if (is_empty) {
free_pinned_region<false>(hr);
}
} else if (hr->is_closed_archive()) {
// nothing to do with closed archive region
} else {
//MarkSweepDeadRatio默认5
assert(MarkSweepDeadRatio > 0,
"only skip compaction for other regions when MarkSweepDeadRatio > 0");
// Too many live objects; skip compacting it.
_collector->update_from_compacting_to_skip_compacting(hr->hrm_index());
//region如果是年轻代的,需要创建Block Offset Table
if (hr->is_young()) {
// G1 updates the BOT for old region contents incrementally, but young regions
// lack BOT information for performance reasons.
// Recreate BOT information of high live ratio young regions here to keep expected
// performance during scanning their card tables in the collection pauses later.
hr->update_bot();
}
log_trace(gc, phases)("Phase 2: skip compaction region index: %u, live words: " SIZE_FORMAT,
hr->hrm_index(), _collector->live_words(hr->hrm_index()));
}
}
// Reset data structures not valid after Full GC.
//清除rem_set与cardtable信息
reset_region_metadata(hr);
return false;
}
如果准备阶段发现!task.has_freed_regions()
regions不够用,就需要用到serial的gc,调用prepare_serial_compaction
phase3_adjust_pointers
G1FullGCAdjustTask
void G1FullGCAdjustTask::work(uint worker_id) {
Ticks start = Ticks::now();
ResourceMark rm;
// Adjust preserved marks first since they are not balanced.
G1FullGCMarker* marker = collector()->marker(worker_id);\
//调整stack中的对象地址,前面的region已经回收了
marker->preserved_stack()->adjust_during_full_gc();
// Adjust the weak roots.
if (!Atomic::cmpxchg(&_references_done, false, true)) {
G1CollectedHeap::heap()->ref_processor_stw()->weak_oops_do(&_adjust);
}
AlwaysTrueClosure always_alive;
_weak_proc_task.work(worker_id, &always_alive, &_adjust);
CLDToOopClosure adjust_cld(&_adjust, ClassLoaderData::_claim_strong);
CodeBlobToOopClosure adjust_code(&_adjust, CodeBlobToOopClosure::FixRelocations);
//回到了第一个标记阶段
_root_processor.process_all_roots(&_adjust, &adjust_cld, &adjust_code);
// Now adjust pointers region by region
//逐个region进行处理
G1AdjustRegionClosure blk(collector(), worker_id);
G1CollectedHeap::heap()->heap_region_par_iterate_from_worker_offset(&blk, &_hrclaimer, worker_id);
log_task("Adjust task", worker_id, start);
}
phase4_do_compaction
void G1FullGCCompactTask::work(uint worker_id) {
Ticks start = Ticks::now();
GrowableArray<HeapRegion*>* compaction_queue = collector()->compaction_point(worker_id)->regions();
for (GrowableArrayIterator<HeapRegion*> it = compaction_queue->begin();
it != compaction_queue->end();
++it) {
//将标记对象取出后,移动到目标地址,随后清除next_mark_bitmap
compact_region(*it);
}
//重新设置region是否需要压缩
G1ResetSkipCompactingClosure hc(collector());
G1CollectedHeap::heap()->heap_region_par_iterate_from_worker_offset(&hc, &_claimer, worker_id);
log_task("Compaction task", worker_id, start);
}
压缩就是复制,每一个对象存了新地址的
size_t G1FullGCCompactTask::G1CompactRegionClosure::apply(oop obj) {
size_t size = obj->size();
HeapWord* destination = cast_from_oop<HeapWord*>(obj->forwardee());
if (destination == NULL) {
// Object not moving
return size;
}
// copy object and reinit its mark
HeapWord* obj_addr = cast_from_oop<HeapWord*>(obj);
assert(obj_addr != destination, "everything in this pass should be moving");
Copy::aligned_conjoint_words(obj_addr, destination, size);
//初始化就是更新对象mark word
cast_to_oop(destination)->init_mark();
assert(cast_to_oop(destination)->klass() != NULL, "should have a class");
return size;
}