G1垃圾收集器

本文只是随手记录,不一定完全正确

存储概念

G1算法将堆划分为若干个区域(Region),但仍然属于 分代收集器。
在G1中还有一种特殊的区域,叫Humongous区域。
如果一个对象占用的空间超过了分区容量50%以上,G1收集器就认为这是一个巨型对象。
这些巨型对象,它是一个短期存在的巨型对象,就会对垃圾收集器造成负面影响。为了解决这个问题,G1划分了一个Humongous区,它用来专门存放巨型对象。
如果一个H区装不下一个巨型对象,那么G1会寻找连续的H分区来存储。为了能找到连续的H区,有时候不得不启动Full GC(这里有疑问,G1 是没有fullGC概念的)。
G1垃圾收集器

Rset 和 card Table

GC 新生代对象,我们如何找到所有的根对象呢? 老年代的所有对象都是根么?那这样扫描下来会耗费大量的时间。于是,G1引进了RSet的概念。
它的全称是Remembered Set,作用是跟踪指向某个heap区内的对象引用。
配合card table (卡表),卡表将分区分成一个个逻辑上连续的卡,如果被引用了,这个卡表就会记录这个卡被脏引用了,
rset 也会记录这个数组的下标
G1垃圾收集器

Young GC和Mixed GC

G1提供了两种GC模式,Young GC和Mixed GC,两种都是完全Stop The World的.

  • Young GC:选定所有年轻代里的Region。通过控制年轻代的region个数,即年轻代内存大小,来控制young GC的时间开销。

  • Mixed GC:选定所有年轻代里的Region,外加根据global concurrent marking统计得出收集收益高的若干老年代Region。在用户指定的开销目标范围内尽可能选择收益高的老年代Region。

    由上面的描述可知,Mixed GC不是full GC,它只能回收部分老年代的Region,如果mixed GC实在无法跟上程序分配内存的速度,导致老年代填满无法继续进行Mixed GC,就会使用serial old GC(full GC)来收集整个GC heap。所以我们可以知道,G1是不提供full GC的

Young GC:

阶段1:根扫描
静态和本地对象被扫描
阶段2:更新RS
处理dirty card队列更新RS
阶段3:处理RS
检测从年轻代指向年老代的对象
阶段4:对象拷贝
拷贝存活的对象到survivor/old区域
阶段5:处理引用队列
软引用,弱引用,虚引用处理

Mixed GC:

Mixed GC:选定所有年轻代里的Region,外加根据global concurrent marking统计得出收集收益高的若干老年代Region。在用户指定的开销目标范围内尽可能选择收益高的老年代Region。

阶段1:初始标记(initial mark,STW)标记了从GC root开始直接可达的对象。
它共用了young GC的暂停,这是因为他们可以复用root scan操作,所以可以说global concurrent marking是伴随Young GC而发生的
阶段2 :并发标记(Concurrent Marking)。(关系到三色标记法,和 与CMS的区别)
这个阶段从GC Root开始对heap中的对象标记,标记线程与应用程序线程并行执行,并且收集各个Region的存活对象信息。
阶段3 :最终标记(Remark,STW)
该阶段是 STW 回收,帮助完成标记周期。G1 GC 清空 SATB 缓冲区,跟踪未被访问的存活对象,并执行引用处理。
阶段四 : 清除垃圾(Cleanup,STW)
在这个最后阶段,G1 GC 执行统计和 RSet 净化的 STW 操作。在统计期间,G1 GC 会识别完全空闲的区域和可供进行混合垃圾回收的区域。清理阶段在将空白区域重置并返回到空闲列表时为部分并发。

三色标记算法

提到并发标记,我们不得不了解并发标记的三色标记算法。
它是描述追踪式回收器的一种有用的方法,利用它可以推演回收器的正确性。 首先,我们将对象分成三种类型的。
黑色:根对象,或者该对象与它的子对象都被扫描
灰色:对象本身被扫描,但还没扫描完该对象中的子对象
白色:未被扫描对象,扫描完成所有对象之后,最终为白色的为不可达对象,即垃圾对象

CMS和 G1并发标记的不同

由于是并发的,所以有可能 白色对象,有时候变换了父对象。所以有如下2中可行的方式:

  • 在插入的时候记录对象
  • 在删除的时候记录对象

刚好这对应CMS和G1的2种不同实现方式:

CMS采用的是增量更新(Incremental update),

只要在写屏障(write barrier)里发现要有一个白对象的引用被赋值到一个黑对象 的字段里,那就把这个白对象变成灰色的。即插入的时候记录下来。

G1使用的是STAB(snapshot-at-the-beginning)的方式

删除的时候记录所有的对象,它有3个步骤:

1,在开始标记的时候生成一个快照图标记存活对象
2,在并发标记的时候所有被改变的对象入队(在write barrier里把所有旧的引用所指向的对象都变成非白的)
3,可能存在游离的垃圾,将在下次被收集

参考资料 :

  • 初级:
    https://blog.csdn.net/qqqqq1993qqqqq/article/details/71882733
    美团技术团队:
    https://tech.meituan.com/2016/09/23/g1.html
  • 高级:对照论文解析
    https://mp.weixin.qq.com/s/V9R0r0aZsxQjcTSxMoHTRw
上一篇:PHP共享内存yac操作类


下一篇:mac安装mysql及导库