Abstract
JVM中有众多的垃圾收集器,每一种使用的技术或者引用场景均不相同,这篇文章简述一下常用的GC。
- PSGC
- G1
- Shenandoah
- ZGC
- CMS
Introduction
Technology
Overview of GC
在可达性分析的GC过程中,可以大致分为两个过程:Mark(标记)阶段,Sweep/Compact/Copy阶段。(对于使用Compact/Copy方式回收堆的GC,最终还需要更新所有的reference,通常分为两步:更新所有root自身reference,由root节点更新其引用对象,递归的更新. Note:)
Shenandoah
Prallel Scavenge
G1
G1是一款响应时间优先的Region-based垃圾回收器,G1允许设置通过MaxGCPauseMillis参数给JVM的GC过程占用时间设置一个软限制(该限制不确保一定能达到),通过使用启发式算法,利用以往的region回收数据,计算需要回收的old region数量,来达到软限制的目的。##
G1在第JDK9中已经替换CMS成为JDK的默认GCJEP 248。
存在垃圾收集器通过使GC过程能中断,来实现硬时间限制。
在分代模型的JVM中,存在两种GC:Minor GC以及Full GC,G1的一个目的就是为了减少Full GC。 Minor GC在所有GC中都会STW,但因为需要处理的数据量小,时间短,虽然执行频繁,但总停顿时间仍然能接受。## Full GC在JVM中可能会出现长停顿,或者占用大量的CPU资源,虽然相对出现次数较少,仍然是一个对系统有很大影响。 G1通过提供一种新的GC策略:Mixed GC,将部分old generation的数据在Mixed GC中回收,减少Full GC的次数。
Minor GC
G1的Minor GC使用copy算法(cheery算法迭代复制),在此过程中STW,GC过后会动态调整young region的大小(使用空闲region列表扩展##)
类似于ParNew##.
Minor GC过程:
- STW
- CSet = young regions
- Parallel Tasks
-
- 扫描所有根对象,并复制到Survivor区域(所有CSet都会被回收,所以CSet的RemSet不需要更新)
-
- 处理所有CSet之外的region到CSet的引用:将该部分视为root
-
-
- 复制obj到新的Survivor区域,对于obj引用的对象,若obj.field 在CSet中,则深度优先,将该obj.file加入处理队列中,若obj.field不在Cset中,则更新其RemSet.
-
- 其他任务:处理GC使用的空间,内存扩展,决定是否进行Mixed GC等步骤.
Note: 不使用 Card Table进行代际引用搜索。
Mixed GC
和Minor GC以及Major GC(Full GC)相比,Mixed GC将会收集全部young region以及部分old region.## Mixed GC可以分为两个大部分:Concurrent Mark 以及 Parallel Compact两个过程。 和Minor GC相比,Mixed GC使用STAB(Snapshot At the Beginning)以支持Concurrent Mark。
因此和PSGC相比,在G1中一共使用了两个write barrier,一个处理RemSet,一个处理GC过程中的STAB.
Mixed GC过程:
* : Mark阶段, ** : 清理阶段
- (Initial Mark)初始标记(STW)* Mixed GC只会在YGC之后运行,会用YGC保存在Survivor的结果作为根,不在需要一轮单独的Initial Mark.
- (Root Region Scanning) 扫描,因为借用了YGC的结果,这一阶段必须在YGC发生之前。
- (Concurrent Mark)并发标记* 使用STAB,Remember Set和Write Barrier实现并发标记,这一阶段在达到
InitiatingHeapOccupancyPercent阈值之后启动,此过程中会记录每个Region的相关信息,用于Compact整理阶段 - (Remark)再标记(STW)* 这个阶段可以Parallel,目的是为了结束标记过程。因为Concurrent Mark过程可能一直有STAB处理,在这里处理完所有的引用变更。
ParallelGCThreads可以设置该过程使用的线程数目。 - (Clean Up)清理阶段*
- Compact **
Full GC
G1的Full GC使用mark-sweep-compact算法实现,在JEP 307中由单线程改为了Parallel。
Shenandoah
Shenandoah是一款面向大堆的低延迟Region-based垃圾收集器,最初由Red-Hat开发。 Shenandoah的几个特点:
- 1)相比G1,并发回收,做到了尽可能的并发,延迟大大降低(当然,牺牲了一点吞吐量)。
- 相比G1,不提供分代的region.
- 不使用Remember Set记录region之间引用关系,使用邻接矩阵?是吗?##
- 为了实现1),使用Brooks forward指针,因此
-
- 1)添加了一个read barrier(性能有损失);
-
- 2)修改了object layout:添加forward头
-
- 3)GC并发copy过程中实现了一个write barrier来保证 两个object的一致性(论文中花费时间只有:100+ms/2h)
- 更新引用关系需要再次扫描堆,因此留到下一次GC过程中。
- STAB
- Barrier
- [ ]
Reference
- VEE'20 Deconstructing the Garbage-First Collector
- Garbage First Garbage Collection
- Shenandoah: An open-source concurrent compacting garbage collector for OpenJDK