首页 > 编程知识 正文

g1垃圾回收算法,g1垃圾回收过程

时间:2023-05-04 11:59:42 阅读:14976 作者:1645

G1垃圾收集器GC收集器的三个考虑事项:

随着所使用的内存(等待时间)吞吐量(Throughput )硬件成本的降低,机器的内存也变大,GC收集器使用的内存基本上是可接受的。 吞吐量可以通过集群(增加机器)来解决。

随着JVM中内存的增长,STW的时间成为了JVM紧急解决的问题,如果仍然使用传统的分代机型,则STW的时间将变得越来越长。

传统的垃圾收集器无法预测STW的时间。 有没有方法先定义休眠时间,反向推测收集内容? 正如领导者年初制定KPI那样,分配的任务多则多做,分配的任务少则少做。

G1的想法也很相似。 我每次都不要求清理垃圾。 我只是在努力做我认为正确的事。

我们要求G1在任意一秒钟内停顿不得超过10ms,这就是制定KPI的原因。 G1尽量实现这个目标,反向估计这次收集的大致区域,可以逐步完成收集。

这也是必须使用G1垃圾收集器(-XX: UseG1GC )设置的参数之一。 -XX:MaxGCPauseMillis=10。

G1的堆内存分割为了实现STW的时间预测,首先需要思想上的变化。 G1将堆存储器“归零”,将堆存储器分割为多个大小相等的独立区域(Region )。 每个Region都可以根据需要扮演新生代感人的关键空间、Survivor空间、或者老年代的空间。 收集器可以对扮演不同角色的Region应用不同的策略进行处理。 这样,无论是新创建的对象,还是已经存在并多次收集的旧对象,都可以获得良好的收集效果。

Region可能是感动的关键,也可能是Survivor,也可能是Old。 另外,Region中还有用于存储大对象的特别的Humongous区域。 G1认为只有尺寸超过Region容量的一半的对象才能判定为大对象。 每个Region的大小可以由参数-XX:G1HeapRegionSize设置,值的范围必须在1mb到32mb之间,并且必须是2的n次方。 对于超过整个Region容量的超大型对象,其存储在n个连续的Humongous Region中,并且G1的回收在大多数情况下将Humongous Region视为上一代的一部分。

G1在逻辑上还是分为感动的关键、Survivor、OLd,但在物理上他们是不连续的。

G1的运转过程

G1的执行过程与CMS基本一致,分为以下4个步骤。

初始标签(Initial俊秀香烟ing ) )只要标记直接与GC Roots关联的对象,就可以更改TAMS指针的值,以便在下一阶段的用户线程同时运行时,将新对象添加到可用的Region中在此阶段,线程需要停止,但G1收集器在此阶段实际上没有额外的停止,因为它需要时间,而且在运行Minor GC时同步进行。 通过并发标记(Concurrent俊秀的烟草ing ) GC Root进行堆中对象的可达性分析,递归扫描整个堆的对象贴图以找到要回收的对象。 在这个阶段需要时间,但可以与用户程序同时运行。 扫描对象图时

跟踪完成后,具有并发引用更改的对象将出现标记遗漏问题。 在G1中,使用快照-自动贝叶斯(satb )算法进行解析。 后面会详细叙述。 最终聚集标记(Final俊秀烟草ing )对用户线程进行临时暂停,并处理即使在同时标记阶段也保留的最后少量SATB记录(标记遗漏对象)。 实时数据计数和评估(Live Data Counting and Evacuation ) :负责Region统计数据的更新,对每个Region的回收价值和成本进行排名,并根据用户期望的休眠时间制定回收计划。 可以自由选择任意数量的Region来配置回收,并将决定回收的某些Region的生存对象复制到空Region中,这里的操作与生存对象的移动相关,需要暂停用户线程,多个收集器线程并行执行什么是TAMS? 为了实现GC和用户线程的并发,需要解决回收过程中新对象的分配,G1在每个区域设计了两个指针: tams (顶俊秀香烟Start ),从区域开始统一分配这样的对象认为它们是生存的,不包括在垃圾回收范围内。

三色标记在三色标记法之前有一种叫做俊秀的香烟-And-Sweep (标记清除)的算法。 该算法设置用于记录对象是否正在使用的标志位。 一开始所有的标记位都为0,如果知道对象是可以到达的,就设定为1,一步一步的话,结果就像树一样。 标记步骤完成后,将所有未标记的对象一起清理,然后再次将所有标记位设置为0,以便于下次清理。

该算法最大的问题是,在GC运行过程中需要完全暂停整个程序,无法实现用户线程和GC线程的并行执行。 由于标记清扫法的标志位0和1在不同的阶段有不同的意义,所以新添加的对象无论标记的理由如何都有可能错误地删除该对象。 在要求实时性的系统中,需要这种长时间挂起的标记清扫法是不能接受的。 因此,需要一种算法来解决GC运行时程序长时间锁定的问题。 那就是三色表示法。

三色标记的最大好处是可以异步执行,从而以极少的中断时间或完全无中断地执行整个GC。

p>

三色标记法很简单。首先将对象用三种颜色表示,分别是白色、灰色和黑色。

黑色:表示根对象,或者该对象与它引用的对象都已经被扫描过了。灰色:该对象本身已经被标记,但是它引用的对象还没有扫描完。白色:未被扫描的对象,如果扫描完所有对象之后,最终为白色的为不可达对象,也就是垃圾对象。

漏标问题

假设此时,对象A及其引用的对象都已经被扫描完,那么对象A将会被标记为黑色。用户线程将对象B和对象C之间的引用断开,将对象A指向对象C,此时对象C会被当成垃圾对象,会产生漏标问题,因为对象A不会再被扫描。

漏标问题在CMS和G1收集器中有着不同的解决方案。

CMS:采用IncrementalUpdate(增量更新)算法,在并发标记阶段时如果一个白色对象被一个黑色对象引用时,会将黑色对象重新标记为灰色,让垃圾收集器在重新标记阶段重新扫描。G1:采用SATB(snapshot-at-the-beginning),在初始标记时做一个快照,当B和C之间的引用消失时要把这个引用推到GC的堆栈,保证C还能被GC扫描到,在最终标记阶段扫描STAB记录。

两种漏标解决方案的对比:

SATB算法关注的是引用的删除(B->C的引用)。Incremental Update算法关注的是引用的增加(A->C 的引用),需要重新扫描,效率低。 记忆集与卡表

跨代引用:堆空间通常被划分为新生代和老年代。由于新生代的垃圾收集通常很频繁,如果老年代对象引用了新生代的对象,那么回收新生代的话,需要扫描所有从老年代到新生代的所有引用,所以要避免每次YGC时扫描整个老年代,减少开销。


记忆集(RSet,Remembered Set):用来记录从其他Region中的对象到本Region的引用,是一种抽象的数据结构。每一个Region都设有一个RSet,有了这个数据结构,在回收某个Region的时候,就不必对整个堆内存的对象进行扫描了,它使得部分收集成为了可能。

对于年轻代的Region,它的RSet只保存了来自老年代的引用,这是因为年轻代的回收是针对所有年轻代Region的,没必要画蛇添足。所以说年轻代Region的RSet有可能是空的。

而对于老年代的Region来说,它的RSet也只会保存老年代对它的引用。这是因为老年代回收之前,会先对年轻代进行回收。这时,感动的钥匙区变空了,而在回收过程中会扫描Survivor分区,所以也没必要保存来自年轻代的引用。

RSet通常会占用很大的空间,大约5%或者更高(最高可能20%)。不仅仅是空间方面,很多计算开销也是比较大的。

RSet究竟是怎么辅助GC的呢?在做YGC的时候,只需要选定年轻代的RSet作为GC ROOTs,这些RSet记录了old->young的跨代引用,避免了扫描整个老年代。 而mixed gc的时候,老年代中记录了old->old的RSet,young->old的引用从Survivor区获取(老年代回收之前,会先对年轻代进行回收,存活的对象放在Survivor区),这样也不用扫描全部老年代,所以RSet的引入大大减少了GC的工作量。

安全点与安全区域

用户线程暂停,GC线程要开始工作,但是要确保用户线程暂停的这行字节码指令是不会导致引用关系的变化。所以JVM会在字节码指令中,选一些指令,作为“安全点”,比如方法调用、循环跳转、异常跳转等,一般是这些指令才会产生安全点。

为什么它叫安全点,是这样的,GC时要暂停用户线程,并不是抢占式中断(立马把业务线程中断)而是主动式中断。

主动式中断是设置一个标志,这个标志是中断标志,各用户线程在运行过程中会不停的主动去轮询这个标志,一旦发现中断标志为 True,就会在自己最近的“安全点”上主动中断挂起。

为什么需要安全区域?要是用户线程都不执行(用户线程处于Sleep或者是Blocked状态),那么程序就没办法进入安全点,对于这种情况,就必须引入安全区域。安全区域是指能够确保在某一段代码片段之中, 引用关系不会发生变化,因此,在这个区域中任意地方开始垃圾收集都是安全的。我们也可以把安全区域看作被扩展拉伸了的安全点。

当用户线程执行到安全区域里面的代码时,首先会标识自己已经进入了安全区域,这段时间里JVM要发起GC就不必去管这个线程了。

当线程要离开安全区域时,它要检查JVM是否已经完成了根节点枚举或者其他GC中需要暂停用户线程的阶段:
1、如果完成了,那线程就当作没事发生过,继续执行。
2、否则它就必须一直等待,直到收到可以离开安全区域的信号为止。

更多精彩内容关注本人公众号:架构师升级之路

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。