“这是我参与8月更文挑战的第26天,活动详情查看:8月更文挑战”
🔉引言
今天回来的早,心情也还好,我开心的时候希望和你们一起开心,我难过的时候不希望你们难过,因为我是不会告诉你们的🙀,闲话少说,开始今天的正题吧。
🌲Shenandoah收集器
❤️工作流程
今天我们来讲一讲它的工作流程,内容呢,来自于以Shenandoah在2016年的论文,工作流程大致分为9个阶段:
- 初始标记(
initial Marking) - 并发标记(
Concurrent Marking) - 最终标记(
Final Marking) - 并发清理(
Concurrent Cleanup) - 并发回收(
Concurrent Evacation) - 初始引用更新(
initial Update Reference) - 并发引用更新(
Concurrent Update Reference) - 最终引用更新(
Final Update Reference) - 并发清理(
Concurrent Cleanup)
MyGOd,这么多啊,咋弄呢?咋一看好多哈,但是 Shenandoah收集器不是G1的继承者嘛,那肯定有相同的啊,等等,我能说我G1还没学会嘛?那你不赶紧回忆回忆G1?昂,前三个阶段都一样啊,那就简要的说一下吧。
🌟 初始标记
初始标记主要标记可直接被GCRoots关联的对象,这个阶段耗时很短,需要停顿线程,停顿时间与堆大小无关,与GCRoots的数量有关。
🌟并发标记
从GCRoots开始,对堆中对象进行可达性分析,标记存活对象,该阶段耗时长,可与用户线程并发执行,时间长短取决于堆中存活对象的数量和对象图的复杂度。
🌟最终标记
对用户线程做一个简单暂停,用于处理并发阶段结束后仍遗留下来的少量的SATB记录,并统计回收价值最高的Region,并将多个Region组成一个回收集(Collection Set)。
🌟并发清理
这个阶段,先把一个存活对象都没有的Region干掉,一个都没有,还占着空间干什么?抓紧腾地方。
🌟并发回收
接下来,搞哪块呢?嗯,没有存活的对象的Region搞完了,接下来应该是有存活对象的呗,嘿嘿,前面不是搞了个回收集嘛,拿来吧你,先把记忆集里面的存活对象,复制一份到未使用的Region中,这不是移动对象嘛,移动这个事情,如果是暂停用户线程那倒比较简单,我看了一眼是不是并发,竟然是并发我倒吸了一口凉气,并发的话就不好弄,因为移动是一个一次性的过程,移动之后,引用的地址都会发生变化,这个时候再进行对象访问就会:比较麻烦,而且一次性把引用的地址都更新也是很困难的。
那Shenandoah是怎么玩的呢?它是靠一个读屏障和转发指针(Brooks Pointers),关于转发指针这里先按下不表,那由于处理的是回收集,所以时间的长短取决于回收集的大小。
🌟初始引用更新
那有了对象移动自然就有引用更新了,引用更新就这个阶段来做,但该阶段只是一个初始化阶段,并不做具体的处理,只是为了建一个线程集合点,确保所有并发阶段的回收线程都已完成任务,什么任务呢?就是对象分配的任务(此对象,非彼对象哦😜),初始引用更新时间很短,也会产生一个非常短暂的停顿。
🌟并发引用更新
该阶段才算真正的干活阶段,与用户线程并发,由于是干修改值的活,所以时间的长短取决于引用的多少,与并发标记不同,不需要按照 对象图搜索,只需要按照内存物理地址的顺序,线性的搜索出引用类型,然后更改值即可。
🌟最终引用更新
堆中的引用更新搞完了,但GCRoots引用还没弄呢,所以这个阶段搞它,停顿时间与GCRoots的数量有关,这也是Shenandoah的最后一次停顿。
🌟并发清理
那前面的准备工作都做完了之后,可以保证回收集的Region里面没有存活的对象了,那就可以回收该Region,供以后新对象的分配使用。
结合图效果会更好哦,图如下:
📝题外话
有些人感觉到人类的愿望和目的毫无意义,而自然界和思维世界却显露出崇高与奇妙的秩序。个人的存在给他的感受如同监狱一般,他想将宇宙作为一个统一的有意义的整体去体验。这种宇宙宗教情怀在人类早期的发展阶段已现端倪,比如在大卫的《诗篇》以及一些先知那里。佛教中包含的这种宇宙宗教情怀的成分更强烈,这一点可以从叔本华的美妙文章中感受得到。
大声告诉我:你们知道叔本华嘛?