学习记录--《垃圾回收算法》
一、CMS大方面有4阶段
ps: 这里需要解释一下,本来有6个阶段,其中有两个准备阶段
- 第一个阶段:initial mark初始标记
- 第二个阶段:concurrent mark并发标记
- 第三个阶段:remark重新标记
- 第四个阶段:concurrent sweep并发的回收
这里有两个并发阶段,只要在JVM看到concurrent这个,就说明是我的垃圾回收线程和我的工作线程在一块工作。
- 第一个阶段:通过GCRoots找到跟对象(此过程STW,但是时间很短)
- 第二阶段:并发标记会发生很多次,而且在并发的同时,其他工作线程也在不断改变这些引用的指向,这个阶段最耗时间,所以选择并发执行(即不产生STW,响应比较及时), 如果是在并发标记过程中变成非垃圾(有引用指向),这时候就会进入remark阶段
- 第三阶段:有些垃圾有了引用指向,需要重新标记,从垃圾变成不是垃圾,把漏标的重新标记(此过程STW,但是时间很短)
- 第四阶段:把不用的垃圾回收,回收的过程中产生新垃圾,也就是浮动垃圾,会在下一轮进行回收
二、G1
-
简单介绍
- G1是一种服务端应用使用的垃圾回收器,目标是用在多核、大内存的机器上,他在大多数情况下可以实现执行的GC暂停时间,同时还能保持较高的吞吐量,他是在逻辑上分代物理上不分代的。
- G1的内存分为一个一个Region
- 每一份region在逻辑上依然属于某一个分代,这个分代分为4种,第一种old去都是放老对象的、survivor放存活对象、Eden放新生对象、Humongous大对象区域,对象特别大可能会跨两个region
-
特点
- 并发收集
- 压缩空闲时间不会延长GC的暂停时间
- 更易预测GC暂停时间
- 使用不需要实现很高的吞吐量场景
PS:CMS也是并发手机,他们两个在算法本质上没区别,但是ZGC和Shenandoah的算法就有本质区别,那两个是颜色指针(color pointer)- 三色标记:把对象分为三个不同颜色,没个不同颜色是标志他到底有没有标记过,还是标记一半了,还是没有标记
- 颜色指针:一个指针猜我们内存中没有进行压缩他是64位的,他会拿出3位,在其中做一下标记,来记录变化过的指针
-
G1的两个概念
- CSet(Collection Set):有哪些需要被回收,会收集到表格里
- RSet(Remember Set):每一个Region里面他都有一个表格(Hash),记录了其他region中对象到本region的引用
-
G1触发时间
- Eden空间不足(YGC)
- Old空间不足或者System.gc();(FGC)
-
G1产生FGC怎么办
- 扩内存
- 提高CPU性能
- 降低MixedGC触发的阈值,让MixedGC提早发生(默认45%)
-
MixedGC(XX:InitiatingHeapOccupancyPercent)
- 相当于一套完整的CMS,混合回收,针对每个Region,哪个满了回收哪个
三、并发标记算法
- CMS和G1用的同一个算法,三色标记
- 把对象在逻辑上分成三种颜色,第一种黑色,他是不是垃圾已经被标记完了,而且成员变量会牵扯它引用的一些对象也已经标记完了,这时候我们称之为黑色。第二种灰色,本身被标记完了,但是还没有标记到它所引用的那些对象,引用的那些对象还是白色的没有标记到。第三种是白色,就是没有被标记到的对象。
- 漏标
- 黑色指向白色,指向白色的其他引用没了。(必须同时具备黑色指向白色,灰色指向白色的没了)
- 在并发标记的线程和我们工作的线程同时进行这个阶段会漏标
- 漏标解决方案
- 增量更新Incremental Update:如上图,A指向D的增加,当A指向D时跟踪这个引用,产生引用后把A标记成灰色,原来不是黑色不扫描,重新标记成灰色,当下次扫描时发现这个灰色对象,那就重新扫描,D又被找到了。这是关注引用的增加。
- SATB(snapshot at the beginning),如上图,B指向D的删除,刚开始做一个快照,当B和D消失的时候把这个引用对到GC的堆栈,保证D还能被GC扫到,最重要的是把这个引用对到GC的堆栈,是灰色对象指向白色的应用,如果引用消失,放到栈,下次直接扫描。这是关注引用的删除
- G1选择是SATB,是因为增量更新变成灰色成员还要重新扫,效率低。当灰色指向白色的引用消失,如果没有黑色指向白色引用会被PUSH到堆栈,下次扫描时拿到这个引用,而且SATB是与RSet一起使用,由于RSet存在,不需要扫描整个堆去查找指向白色的引用,效率高。