概述
上文说到了触发ZGC的垃圾回收的几种场景,本文详细介绍下ZGC的具体步骤
ZDrvier线程
ZGC是有ZDriver负责实际的执行,相关代码如下:
void ZDriver::run_service() {
// Main loop
while (!should_terminate()) {
// 堵塞方式等待GC请求
const ZDriverRequest request = _gc_cycle_port.receive();
if (request.cause() == GCCause::_no_gc) {
continue;
}
// 执行GC
gc(request);
// 通知GC已经完成
_gc_cycle_port.ack();
}
}
void ZDriver::gc(const ZDriverRequest& request) {
ZDriverGCScope scope(request);
// 阶段1: Pause Mark Start
pause_mark_start();
// 阶段2: Concurrent Mark
concurrent(mark);
// 阶段3: Pause Mark End
while (!pause_mark_end()) {
// Phase 3.5: Concurrent Mark Continue
concurrent(mark_continue);
}
// 阶段4: Concurrent Mark Free
concurrent(mark_free);
// 阶段5: Concurrent Process Non-Strong References
concurrent(process_non_strong_references);
// 阶段6: Concurrent Reset Relocation Set
concurrent(reset_relocation_set);
// 阶段7: Pause Verify
pause_verify();
// 阶段8: Concurrent Select Relocation Set
concurrent(select_relocation_set);
// 阶段9: Pause Relocate Start
pause_relocate_start();
// 阶段10: Concurrent Relocate
concurrent(relocate);
}
gc函数中,以concurrent开头表示并发执行,pause表示需要暂停业务线程
阶段1(Pause Mark Start)
void ZHeap::mark_start() {
// Flip address view
flip_to_marked();
// Retire allocating pages
_object_allocator.retire_pages();
// Reset allocated/reclaimed/used statistics
_page_allocator.reset_statistics();
// Reset encountered/dropped/enqueued statistics
_reference_processor.reset_statistics();
// Enter mark phase
ZGlobalPhase = ZPhaseMark;
// Reset marking information and mark roots
_mark.start();
// Update statistics
ZStatHeap::set_at_mark_start(_page_allocator.stats());
}
可以看到ZGC的Pause Mark Start阶段所做的是只是修改状态位,重置统计数据,并不会实际的去标记root对象,因此速度是很快的;
阶段2(Concurrent Mark)
void ZMark::mark(bool initial) {
if (initial) {
ZMarkRootsTask task(this);
_workers->run(&task);
}
ZMarkTask task(this);
_workers->run(&task);
}
阶段2.1 ( Mark Roots)
并发标记阶段传入的initial=true,表示要先标记GC ROOTS;
ZMarkOopClosure _cl;
ZMarkCLDClosure _cld_cl;
ZMarkThreadClosure _thread_cl;
ZMarkNMethodClosure _nm_cl;
virtual void work() {
_oop_storage_set.apply(&cl);
_class_loader_data_graph.apply(&cld_cl);
_java_threads.apply(&thread_cl);
if (!ClassUnloading) {
_nmethods.apply(&nm_cl);
}
_mark->flush_and_free();
}
这里的_oop_storage_set包含哪些内容呢?_oop_storage_set包括5个strong类型和10个weak类型的全局变量;_class_loader_data_graph和_java_threads分别表示类加载器和java线程栈,_nmethods表示JIT编译之后的方法;
static const uint strong_count = 4 JVMTI_ONLY(+ 1);
static const uint weak_count = 8 JVMTI_ONLY(+ 1) JFR_ONLY(+ 1);
1. Universe::_vm_global = OopStorageSet::create_strong("VM Global", mtInternal);
2. _thread_oop_storage = OopStorageSet::create_strong("Thread OopStorage", mtThread);
3. _thread_service_storage = OopStorageSet::create_strong("ThreadService OopStorage", mtServiceability);
4. JNIHandles::_global_handles = OopStorageSet::create_strong("JNI Global", mtInternal);
5. _jvmti_oop_storage = OopStorageSet::create_strong("JVMTI OopStorage", mtServiceability);
1. Universe::_vm_weak = OopStorageSet::create_weak("VM Weak", mtInternal);
2. JNIHandles::_weak_global_handles = OopStorageSet::create_weak("JNI Weak", mtInternal);
3. _oop_storage = OopStorageSet::create_weak("StringTable Weak", mtSymbol);
4. _storages[0] = OopStorageSet::create_weak("StringDedup Requests0 Weak", mtStringDedup);
5. _storages[1] = OopStorageSet::create_weak("StringDedup Requests1 Weak", mtStringDedup);
6. _table_storage = OopStorageSet::create_weak("StringDedup Table Weak", mtStringDedup);
7. _oop_storage = OopStorageSet::create_weak("ResolvedMethodTable Weak", mtClass);
8. _oop_storage = OopStorageSet::create_weak("ObjectSynchronizer Weak", mtSynchronizer);
9. _weak_tag_storage = OopStorageSet::create_weak("JVMTI Tag Weak OopStorage", mtServiceability);
10. _oop_storage = OopStorageSet::create_weak("Weak JFR Old Object Samples", mtTracing);
#define ENUMERATOR_VALUE_RANGE(T, Start, End) \
template<> struct EnumeratorRange<T> { \
static constexpr EnumeratorRangeImpl::Underlying<T> _start{Start}; \
static constexpr EnumeratorRangeImpl::Underlying<T> _end{End}; \
};
ENUMERATOR_VALUE_RANGE(OopStorageSet::StrongId,
OopStorageSet::strong_start,
OopStorageSet::strong_end);
ENUMERATOR_VALUE_RANGE(OopStorageSet::WeakId,
OopStorageSet::weak_start,
OopStorageSet::weak_end);
ENUMERATOR_VALUE_RANGE(OopStorageSet::Id,
OopStorageSet::all_start,
OopStorageSet::all_end);
对于上述的全局变量、java线程栈、类加载器和JIT编译方法,最终是通过ZMarkOopClosure来进行标记的:
class ZMarkOopClosure : public OopClosure {
virtual void do_oop(oop* p) {
const oop o = Atomic::load(p);
const uintptr_t addr = ZOop::to_address(o);
if (ZAddress::is_good(addr)) {
// Mark through good oop
mark_barrier_on_oop_slow_path(addr);
} else {
// Mark through bad oop
barrier<is_good_or_null_fast_path, mark_barrier_on_oop_slow_path>(p, o);
}
}
virtual void do_oop(narrowOop* p) {
ShouldNotReachHere();
}
};
uintptr_t ZBarrier::mark_barrier_on_oop_slow_path(uintptr_t addr) {
uintptr_t good_addr;
if (ZAddress::is_marked(addr)) {
// Already marked, but try to mark though anyway
good_addr = ZAddress::good(addr);
} else if (ZAddress::is_remapped(addr)) {
// Already remapped, but also needs to be marked
good_addr = ZAddress::good(addr);
} else {
// Needs to be both remapped and marked
good_addr = remap(addr);
}
// 标记
ZHeap::heap()->mark_object<true, true, false, false>(good_addr);
return good_addr;
}
inline void ZMark::mark_object(uintptr_t addr) {
ZPage* const page = _page_table->get(addr);
if (page->is_allocating()) {
// Already implicitly marked
return;
}
bool inc_live = false;
// Try mark object
if (!page->mark_object(addr, false, inc_live)) {
// Already marked
return;
}
// Push
ZMarkThreadLocalStacks* const stacks = ZThreadLocalData::stacks(Thread::current());
ZMarkStripe* const stripe = _stripes.stripe_for_addr(addr);
ZMarkStackEntry entry(addr, false, inc_live, true, false);
stacks->push(&_allocator, &_stripes, stripe, entry, false);
}
可以看到GC ROOT的标记相对比较简单,会更新page对象的_livemap,同时会将对象包装成ZMarkStackEntry,放到当前标记线程的ZMarkThreadLocalStacks中,如果当前线程已满,则放到全局的条带stripe中去;
注意的,对于GC ROOTS,ZMarkStackEntry的finalizable=false,follow=true,mark=false;
阶段2.2 ( Mark)
GC ROOTs标记完成之后,开始进行剩余其他对象的标记:
void ZMark::work() {
ZMarkCache cache(_stripes.nstripes());
ZMarkStripe* const stripe = _stripes.stripe_for_worker(_nworkers, ZThread::worker_id());
ZMarkThreadLocalStacks* const stacks = ZThreadLocalData::stacks(Thread::current());
work_without_timeout(&cache, stripe, stacks);
// Flush and publish stacks
stacks->flush(&_allocator, &_stripes);
// Free remaining stacks
stacks->free(&_allocator);
}
从2.1知道,标记GC ROOTS的时候,会将存活的对象放到标记线程的ZMarkThreadLocalStacks或者全局的条带中去;此处会取出GC ROOTS,遍历成员,进行标记:
void ZMark::work_without_timeout(ZMarkCache* cache, ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks) {
ZStatTimer timer(ZSubPhaseConcurrentMark);
ZMarkNoTimeout no_timeout;
for (;;) {
if (!drain(stripe, stacks, cache, &no_timeout)) {
break;
}
//试图从其他的条带窃取任务,如果成功,则继续标记
if (try_steal(stripe, stacks)) {
continue;
}
//如果是0号worker线程,通过handshake方式暂停其他线程,将线程的ZMarkThreadLocalStacks刷新到全局的条带中
if (try_proactive_flush()) {
continue;
}
//尝试结束并发标记阶段
if (try_terminate()) {
break;
}
}
}
bool ZMark::drain(ZMarkStripe* stripe, ZMarkThreadLocalStacks* stacks, ZMarkCache* cache, T* timeout) {
ZMarkStackEntry entry;
// Drain stripe stacks
while (stacks->pop(&_allocator, &_stripes, stripe, entry)) {
mark_and_follow(cache, entry);
// Check timeout
if (timeout->has_expired()) {
// Timeout
return false;
}
}
// Success
return !timeout->has_expired();
}
真正的执行标记的路径见mark_and_follow:
void ZMark::mark_and_follow(ZMarkCache* cache, ZMarkStackEntry entry) {
// Decode flags
const bool finalizable = entry.finalizable();
const bool partial_array = entry.partial_array();
if (partial_array) {
follow_partial_array(entry, finalizable);
return;
}
// Decode object address and additional flags
const uintptr_t addr = entry.object_address();
const bool mark = entry.mark();
bool inc_live = entry.inc_live();
const bool follow = entry.follow();
ZPage* const page = _page_table->get(addr);
// 检查_livemap,如果发现已经标记过,则忽略
if (mark && !page->mark_object(addr, finalizable, inc_live)) {
return;
}
// 如果需要更新存活信息
if (inc_live) {
const size_t size = ZUtils::object_size(addr);
const size_t aligned_size = align_up(size, page->object_alignment());
cache->inc_live(page, aligned_size);
}
// 是否需要继续标记对象的成员
if (follow) {
if (is_array(addr)) {
follow_array_object(objArrayOop(ZOop::from_address(addr)), finalizable);
} else {
follow_object(ZOop::from_address(addr), finalizable);
}
}
}
void ZMark::follow_object(oop obj, bool finalizable) {
if (finalizable) {
ZMarkBarrierOopClosure<true > cl;
obj->oop_iterate(&cl);
} else {
ZMarkBarrierOopClosure<false> cl;
obj->oop_iterate(&cl);
}
}
obj.oop_iterate调用的是oopDesc::oop_iterate(OopClosureType* cl) { OopIteratorClosureDispatch::oop_oop_iterate(cl, this, klass()); }
,根据obj对象的不同类型,最终调用的方法也不一样:
- 如果obj的类型是InstanceKlass,最终调用
template <typename T, class OopClosureType>
ALWAYSINLINE void InstanceKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
if (Devirtualizer::do_metadata(closure)) {
Devirtualizer::do_klass(closure, this);
}
oop_oop_iterate_oop_maps<T>(obj, closure);
}
- 如果obj的类型是InstanceRefKlass,即java/lang/ref/Reference子类,最终调用
template <typename T, class OopClosureType>
void InstanceRefKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
InstanceKlass::oop_oop_iterate<T>(obj, closure);
oop_oop_iterate_ref_processing<T>(obj, closure);//引用对象处理
}
从上面的源码看到,如果对象是Reference类型,会进行额外的处理:
void InstanceRefKlass::oop_oop_iterate_discovery(oop obj, ReferenceType type, OopClosureType* closure, Contains& contains) {
// 如果referent对象是活跃的,或者根据soft_reference_policy,本次不需要回收,直接返回
if (try_discover<T>(obj, type, closure)) {
return;
}
// 处理referent对象
do_referent<T>(obj, closure, contains);
//_discovered_list
do_discovered<T>(obj, closure, contains);
}
- 如果obj的类型是InstanceMirrorKlass,最终调用
void InstanceMirrorKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
InstanceKlass::oop_oop_iterate<T>(obj, closure);
if (Devirtualizer::do_metadata(closure)) {
Klass* klass = java_lang_Class::as_Klass_raw(obj);
if (klass != NULL) {
if (klass->class_loader_data() == NULL) {
return;
} else if (klass->is_instance_klass() && klass->class_loader_data()->has_class_mirror_holder()) {
Devirtualizer::do_cld(closure, klass->class_loader_data());
} else {
Devirtualizer::do_klass(closure, klass);
}
}
}
oop_oop_iterate_statics<T>(obj, closure);
}
- 如果obj的类型是InstanceClassLoaderKlass,最终调用
template <typename T, class OopClosureType>
inline void InstanceClassLoaderKlass::oop_oop_iterate(oop obj, OopClosureType* closure) {
InstanceKlass::oop_oop_iterate<T>(obj, closure);
if (Devirtualizer::do_metadata(closure)) {
ClassLoaderData* cld = java_lang_ClassLoader::loader_data_raw(obj);
if (cld != NULL) {
Devirtualizer::do_cld(closure, cld);
}
}
}
- 如果obj的类型是ObjArrayKlass,最终调用
void ZMark::follow_array(uintptr_t addr, size_t size, bool finalizable) {
if (size <= ZMarkPartialArrayMinSize) {
follow_small_array(addr, size, finalizable);
} else {
follow_large_array(addr, size, finalizable);
}
}