CMS与G1 三色标记算法

承上启下

jdk8默认回收器ps+po,jdk9默认就是G1了。但是CMS是并行回收的开始

CMS

在这里插入图片描述

CMS :ConcurrentMarkSweep 老年代 并发的,垃圾回收和应用程序同时运行,降低STW的时间(200MS)
CMS有一些问题,所以没有任何版本默认是CMS的,只能手工指定。CMS是MarkSweep,必然会导致碎片,当碎片到一定程度,CMS老年代分配对象分配不下时,使用serialold进行老年代串行回收。
会产生浮动垃圾
解决方案:降低触发CMS的阈值,保持老年代有足够的空间
-XX:CMSInitiatingOccupancyFraction 92% 降低百分比

六个阶段
预处理阶段
初始标记:STW,标记出根对象。因为只标记跟对象,所以很快
并发标记:标记垃圾,浪费80%GC时间,同应用程序一同运行
重新标记:STW,并发处理中产生了新的垃圾,或者有一些垃圾重新被使用,不再是垃圾。因为大部分垃圾在并发标记时处理过了,所以也很快。
并发清理:将产生的垃圾清除掉,但是同时也会产生新的垃圾。也就是浮动垃圾,这种浮动垃圾只能等待下一个垃圾回收进行处理
整理阶段

三色标记,并发标记时的算法

CMS使用的是三色标记+Incremental Update算法
G1使用的是三色标记+snapshot at the begining (SATB)算法
ZGC: Colored Pointers+写屏障
Shenandoah :Colored Pointers+读屏障

在这里插入图片描述

黑色:自身和成员变量均已标记完成
灰色:自身被标记完成,成员变量未被标记
白色:未被标记的对象(垃圾)

漏标情况,会将本来不是垃圾得对象,当作垃圾回收了
在运行态中,1、黑色对象指向了白色对象,2、并且同时,灰色对象取消了白色对象的引用。
就会产生白色对象漏标的情况。
因为黑色对象已经标记完毕,不会再去扫描,并且也没有灰色对象的指向,所以漏标了

漏标的应对,打破这两种条件之一即可

Incremental update 增量更新,关注引用的增加,如果发现黑色指向了白色,把黑色重新标记为白色,remark过程将重新扫描属性。但是会造成重复扫描已扫描过的属性。(CMS对漏标的处理方式)

SATB snapshot at the begining 关注引用的删除,当灰色对象对白色对象的引用删除后,将这个引用推到GC的堆栈中,保证白色对象还是能够被扫描到(G1对漏标的处理方式)
在扫描时拿到这个引用,由于有Rset存在,不需要扫描整个堆去查找指向白色的引用,效率比较高。
SATB配合Rset,使得整个效率提高

G1

不再进行物理分代,而是逻辑分代。Garbage First 垃圾优先 的垃圾回收器

官方入门:https://www.oracle.com/technical-resources/articles/java/g1gc.html
  • 1

The Garbage First Garbage Collector (G1 GC) is the low-pause, server-style generational garbage collector for Java HotSpot VM. The G1 GC uses concurrent and parallel phases to achieve its target pause time and to maintain good throughput. When G1 GC determines that a garbage collection is necessary, it collects the regions with the least live data first (garbage first).

G1是一种服务端应用使用的垃圾收集器,目标使用在多核,大内存的机器上,它在大多数情况下可以实现指定的GC暂停时间,同时还能保持较高的吞吐量
G1的吞吐量比PS+PO降低了10%-15%,但是STW时间控制在200ms左右。需要响应时间优先,使用G1

G1的特点

并发收集(同CMS差不多,三色标记算法。后续的ZGC,shenadoah使用 colored pointer颜色指针算法,颜色指针会拿出3bit来记录引用变化。。)
压缩空闲空间不会延长GC的暂停时间
更易预测的GC暂停时间
适用不需要实现很高吞吐量的场景

G1区域的内存划分

CMS与G1 三色标记算法_第1张图片

逻辑分区Region:Eden区、Survivor区、Old区、Hunmongous区(大对象区,超过单个region的50%就是Hunmongous,并且可以占用连续的多个内存)

G1的内存区域不是固定的eden区或者old区。比如本来是eden区,在垃圾回收之后,可能就会用作old区来使用

G1基本概念

Cset = collection set

一组可被回收的分区的集合
在Cset中存活的数据会在GC过程中被移动到另一个可用分区
Cset的分区可以来自Eden空间,Survivor空间、或者Old空间
Cset占用不到整个堆空间1%大小

cset 收集到了所有非dirty card,当需要垃圾回收时,直接区cset中取

Rset = Remember set

记录了其他Region中的对象到本Region的引用

这样使得垃圾回收器不需要扫描整个堆,来找到谁引用了当前分区中的对象,只需要扫描Rset即可
但是在每次给对象赋引用时,都需要在Rset做一些额外得记录(做的额外的这些记录,在GC中称为写屏障。注意和jvm中的内存屏障不是一个概念!)

每个Region都要有一块区域记录Rset,浪费10%左右空间,ZGC中没有Rset

G1新生代老年代的分配

分代时,新生代和老年代1:2,尽量不要改
G1新老年代比例,5%-60%,尽量不要手工指定。也不要手工指定,因为这是G1预测停顿时间的基准,G1动态调整STW时间,如果发现超过200ms,降低回收比例。

G1 GC何时触发

触发顺序
1、YongGC,会复制存活对象到其他区域
2、达到mixedGC阈值,进行mixedGC,这个时候年轻代,年老代哪个满了,回收哪个
3、Old空间被占满,FullGC开始,使用serial old垃圾回收器,所以尽量不要FullGC

YoungGC:Eden空间不足,多线程并行执行,并且会动态伸缩Eden区大小,把控STW时间

FullGC:Old空间不足,使用Serial old垃圾回收器,所以尽量不要产生FullGC!G1并不是不会触发FGC,如果对象飞快占据空间,仍然会产生FullGC
如果G1产生FullGC(尽量避免FullGC),jdk10之前fullGC都是串行,之后是并行。
处理
1、扩大内存
2、提高CPU性能(回收的快,业务逻辑产生对象的速度固定,垃圾回收快,内存空间越大)
3、降低MixedGC触发的阈值,让MixedGC提早发生(默认是45%)

MixedGC,G1的正常回收过程,相当于CMS
-XX:InitiatingHeapOccupancyPercent 默认值45%,当O超过这个值时,启动mixedGC
1、初始标记
CMS与G1 三色标记算法_第2张图片
2、并发标记
CMS与G1 三色标记算法_第3张图片
3、最终标记
将改变的变量,再次标记一次CMS与G1 三色标记算法_第4张图片
4、并行筛选标记
将最需要回收的对象进行回收,并且在回收时直接将region指向另一块空间,同时进行了压缩,不会像CMS出现太多的碎片CMS与G1 三色标记算法_第5张图片

你可能感兴趣的:(垃圾回收器-G1)