前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如果你精通java虚拟机:新生代垃圾回收YoungGC之后,薪资不止20K

如果你精通java虚拟机:新生代垃圾回收YoungGC之后,薪资不止20K

作者头像
愿天堂没有BUG
发布2022-10-31 11:27:48
3620
发布2022-10-31 11:27:48
举报

Young GC

前文提到,Young GC(以下简称YGC)是指新生代垃圾回收,下面将详细讨论G1的YGC过程。

选择CSet

YGC的回收过程位于 G1CollectedHeap::do_collection_pause_at_safepoint(),在进行垃圾回收前它会创建一个清理集CSet(Collection Set),存放需要被清理的Region。选择合适的Region放入CSet是为了让G1达到用户期望的合理的停顿时间。CSet的创建过程如代码清单11-2所示:

代码清单11-2 选择Region放入CSet

代码语言:javascript
复制
void G1Policy::finalize_collection_set(...) {
// 先选择新生代Region,用户期望的最大停顿时间是target_pause_time_ms
// G1计算出清理新生代Region的可能用时后,会将剩下的时间(time_remaining_ms)给老年代
double time_remaining_ms =
_collection_set->finalize_young_part(...);
_collection_set->finalize_old_part(time_remaining_ms);
}

G1的YGC只负责清理新生代Region,因此finalize_old_part()不会选择任何Region,所以只需要关注finalize_young_part()。finalize_young_part会在将所有Eden和Survivor Region加入CSet后准备垃圾回收。

G1在evacuate_collect_set()中创建G1ParTask,然后阻塞,直到G1ParTask执行完成,这意味着整个YGC期间应用程序是STW的。类似Parallel GC的YGC,G1ParTask的执行由线程组GangWorker完成,以尽量减少STW时间。不难看出,YGC的实际工作位于G1ParTask,它主要分为三个阶段:

1)清理根集( G1RootProcessor::evacuate_roots);

2)处理RSet( G1RemSet::oops_into_collection_set_do);

3)对象复制( G1ParEvacuateFollowersClosure::do_void)。

清理根集

第一阶段是清理根集。第10章提到HotSpot VM很多地方都属于GCRoot,G1ParTask的evacuate_roots()会从这些GC Root出发寻找存活对象。以线程栈为例,G1会扫描虚拟机所有JavaThread和VMThread的线程栈中的每一个栈帧,找到其中的对象引用,并对它们应用G1ParCopyClosure,如代码清单11-3所示:

代码清单11-3 G1ParCopyClosure

代码语言:javascript
复制
void G1ParCopyClosure<barrier, do_mark_object>::do_oop_work(T* p) {
...
oop obj = CompressedOops::decode_not_null(heap_oop);const InCSetState state = _g1h->in_cset_state(obj);
// 如果对象属于CSet
if (state.is_in_cset()) {
oop forwardee;
markOop m = obj->mark_raw();
if (m->is_marked()) { // 如果已经复制过则直接返回复制后的新地址
forwardee = (oop) m->decode_pointer();
} else { // 将它复制到Survivor Region,返回新地址
forwardee = _par_scan_state->copy_to_survivor_space(...);
}
// 修改根集中指向该对象的引用,指向Survivor中复制后的对象
RawAccess<IS_NOT_NULL>::oop_store(p, forwardee);
...
} else {
...
}
}

清理根集的核心代码是copy_to_survivor_space,它将Eden Region中年龄小于15的对象移动到Survivor Region,年龄大于等于15的对象移动到Old Region。之前根集中的引用指向Eden Region对象,对这些引用应用G1ParCopyClosure之后,Eden Region的对象会被复制到SurvivorRegion,所以根集的引用也需要相应改变指向,如图11-3所示。

图11-3 清理根集

copy_to_survivor_space在移动对象后还会用G1ScanEvacuatedObjClosure处理对象的成员,如果成员也属于CSet,则将它们放入一个G1ParScanThreadState队列,等待第三阶段将它们复制到Survivor Region。总结来说,第一阶段会将根集直接可达的对象复制到Survivor Region,并将这些对象的成员放入队列,然后更新根集指向。

处理RSet

第一阶段标记了从GC Root到Eden Region的对象,对于从OldRegion到Eden Region的对象,则需要借助RSet,这一步由G1ParTask的 G1RemSet::oops_into_collection_set_do完成,它包括更新RSet(update_rem_set)和扫描RSet(scan_rem_set)两个过程。

scan_rem_set遍历CSet中的所有Region,找到引用者并将其作为起点开始标记存活对象。

对象复制

经过前面的步骤后,YGC发现的所有存活对象都会位于G1ParScanThreadState队列。对象复制负责将队列中的所有存活对象复制到Survivor Region或者晋升到Old Region,如代码清单11-4所示:

代码清单11-4 对象复制

代码语言:javascript
复制
template <class T> void G1ParScanThreadState::do_oop_evac(T* p) {
// 只复制位于CSet的存活对象
oop obj = RawAccess<IS_NOT_NULL>::oop_load(p);
const InCSetState in_cset_state = _g1h->in_cset_state(obj);
if (!in_cset_state.is_in_cset()) {
return;
}
// 将对象复制到Survivor Region(或晋升到Old Region)
markOop m = obj->mark_raw();
if (m->is_marked()) {
obj = (oop) m->decode_pointer();
} else {
obj = copy_to_survivor_space(in_cset_state, obj, m);
}
RawAccess<IS_NOT_NULL>::oop_store(p, obj);
// 如果复制后的Region和复制前的Region相同,直接返回
if (HeapRegion::is_in_same_region(p, obj)) {
return;}
// 如果复制前Region是老年代,现在复制到Survivor/Old Region,
// 则会产生跨代引用,需要更新RSet
HeapRegion* from = _g1h->heap_region_containing(p);
if (!from->is_young()) {
enqueue_card_if_tracked(p, obj);
}
}

对象复制是YGC的最后一步,在这之后新生代所有存活对象都被移动到Survivor Region或者晋升到Old Region,之前的Eden空间可以被回收(Reclaim)。另外,YGC复制算法相当于做了一次堆碎片的清理工作,如整理Eden Region可能存在的碎片。

本文给大家讲解的内容是深入解析java虚拟机:新生代垃圾回收(Young GC)

  1. 下篇文章给大家讲解的是深入解析java虚拟机:Mixed GC(混合回收)G1独有的回收策略;
  2. 觉得文章不错的朋友可以转发此文关注小编;
  3. 感谢大家的支持!

本文就是愿天堂没有BUG给大家分享的内容,大家有收获的话可以分享下,想学习更多的话可以到微信公众号里找我,我等你哦。‍

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-03-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 愿天堂没有BUG 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Young GC
  • 本文给大家讲解的内容是深入解析java虚拟机:新生代垃圾回收(Young GC)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档