G1垃圾回收器学习
Posted 程序猿学习笔记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了G1垃圾回收器学习相关的知识,希望对你有一定的参考价值。
学完了CMS,当然得继续学习G1了。
在国庆假期期间写了一部分内容,但感觉理解不够全面,同时也有很多事导致这一篇写的断断续续
1.简介
G1,Garbage-First收集器,使用G1时,它将整个Java堆划分为多个大小相等的独立区域(Region),保留了新生代和老年代的概念,但它们不再是物理隔离的了,它们都是一部分Region(不需要连续)的集合。G1在后台维护了一个优先列表,记录了各个Region回收的价值,每次根据允许的收集时间,优先回收价值最大的Region。这种使用Region划分内存以及有优先级的回收方式,保证了G1收集器在有限的时间内可以获取尽可能高的收集效率。
G1既进行年轻代的回收,也进行老年代的回收。
2.G1的特点
1.并行与并发
2.分代收集。
3.空间整合,年轻代复制算法,老年代标记整理算法,不会产生内存空间碎片。
4.可预测停顿:CMS与G1都关注降低停顿时间,但G1建立可预测停顿模型,-XX:MaxGCPauseMillis设置停顿时间,G1不能保证每次都在这个时限内完成,停顿时间合理可以达到90%以上回收都在这个时限内。
3.回收步骤
在G1里,包含YoungGC和 MixedGC,YoungGC回收年代,MixedGC则回收年轻代和部分回收价值较高的老年代region。如MixedGC无法跟上程序的分配速度,会切换到Serial Old GC 进行整堆的回收(Full GC)。
从高层看,G1的collector一侧其实就是两个大部分:
全局并发标记(Global Concurrent Marking)
拷贝存活对象(Evacuation)
而这两部分可以相对独立执行。
SATB:snapshot at the begining
Global Concurrent Marking基于SATB形式的并发标记。具体分为以下几个阶段:
1.初始标记(Initial marking):暂停阶段。扫描根集合,标记所有根直达对象,并将它们的字段压入扫描栈(Marking Stack)中等待后续扫描。G1使用外部的Bitmap记录mark信息,而不用对象头的Mark Word里的mark bit。在分代式G1模式中,初始标记阶段借用Young GC的暂停,没有额外的、单独的暂停。
2.并发标记(Concurrent marking):并发阶段。不断从扫描栈中取出引用递归扫描整个堆里的对象图。每扫描到一个对象就会对其标记,并将其字段压入扫描栈。重复扫描过程直到扫描栈清空。过程中还会扫描SATB write barrier所记录下的引用。
3.最终标记(final marking,在实现中也叫remarking):暂停阶段。在完成并发标记后,每个Java线程还会剩一些SATB write barrier 所记录的引用未处理。这个阶段负责把剩下的引用处理完。同时这个阶段也进行弱引用处理。
这个和CMS的remark有一个本质上的区别,那就是这个暂停只需要扫描SATB buffer,而CMS的remark则需要扫描mod-union table中的dirty card外加整个根集合,即包含整个年轻代,因此可能CMS remark阶段可能会很慢。
4.清理(Clean up):暂停阶段。清点和重置状态。这个阶段有点像mark-sweep中的sweep阶段,不过不是在堆上sweep实际对象,而是在marking bitmap中统计每个region被标记为活的对象有多少。这个阶段如果发现完全没有活对象的region就会将其整体回收到可分配的region列表中。
Evacuation阶段是全暂停阶段的。它负责把一部分region里的存活对象拷贝到空的region里去,然后回收原region空间。这个阶段可以自由选择多个region来独立收集构成收集集合(Collect Set,CSet),靠pre-region remembered set(RSet)实现。这是regional garbage collector的特征。
在选定CSet后,Evacuation其实就跟Parallel Scavenge的YoungGC类似,采用并行copying(scavenging)算法把CSet里每个region里的存活对象拷贝到新的region里,整个过程完全暂停。G1的Evacuation跟传统的Mark-Compact算法的compaction完全不同:G1会自己从根集合遍历对象图来判定对象生死,后者则是依赖于之前的mark阶段对对象的生死判定。
分代式G1模式下有两种选定CSet的子模式,分别对应YoungGC和MixedGC。
YoungGC:选定所有Young gen里的region,通过控制region个数来控制YoungGC的开销。
MixedGC:选定所有Young gen里的region,外加根据Global Concurrent Marking统计得出收集收益高的若干old gen region。
分代式G1的正常工作流程:在YoungGC与MixedGC之间视情况切换,背后定期做全局并发标记。Initial marking默认搭在YoungGC上执行,在全局并发标记正在工作时,G1不会选择做MixedGC,反之如果有MixedGC正在进行也不会进行Initial Marking。
正常工作流程中,没有FullGC的概念,old gen的收集靠MixedGC来完成。如果MixedGC无法跟上程序分配的速度,会切换到G1之外的Serial Old GC来收集整个堆。FullGC之所以叫FullGC就是要收集整个堆。
本文主要参考了R大的回复、《深入理解Java虚拟机》、Oracle关于G1的介绍以及网络上其他关于G1介绍的文章。
本文主要是记录下学习到关于G1的知识,如有错误,欢迎留言指正。
以上是关于G1垃圾回收器学习的主要内容,如果未能解决你的问题,请参考以下文章