CMS:Concurrent Mark Sweep,以获取最短回收停顿时间为目标的收集器,基于并发“标记清理”实现。JDK1.7之前的默认垃圾回收算法,并发收集,停顿小。
过程:
1、初始标记:stop-the-world,标记GCRoots直接关联的对象
2、并发标记:和用户线程并行执行,标记所有可达对象
3、重新标记:stop-the-world,对并发标记阶段用户线程运行产生的垃圾对象进行标记修正
4、并发清理:清理垃圾对象,和用户线程同时执行
5、并发重置:重置CMS收集器的数据结构
优点:
并发,低停顿
缺点:
1、对CPU非常敏感:在并发阶段虽然不会导致用户线程停顿,但是会因为占用了一部分线程使应用程序变慢
2、无法处理浮动垃圾:在最后一步并发清理过程中,用户线程执行也会产生垃圾,但是这部分垃圾是在标记之后,所以只有等到下一次gc的时候清理掉,这部分垃圾叫浮动垃圾
3、CMS使用“标记-清理”法会产生大量的空间碎片,当碎片过多,将会给大对象空间的分配带来很大的麻烦,往往会出现老年代还有很大的空间但无法找到足够大的连续空间来分配当前对象,不得不提前触发一次FullGC,为了解决这个问题CMS提供了一个开关参数,用于在CMS顶不住,要进行FullGC时开启内存碎片的合并整理过程,但是内存整理的过程是无法并发的,空间碎片没有了但是停顿时间变长了
G1:Garbage First,是一款面向服务端应用的垃圾收集器。
特点:
1、G1垃圾收集器将整个 JVM 内存分为多个大小相等的region,年轻代和老年代逻辑分区 。
2、G1 是 Java9 以后的默认垃圾回收器
3、G1 在整体上使用标记整理算法,局部使用复制算法
4、G1 的每个 Region 大小在 1-32M 之间,可以通过-XX:G1HeapRegionSize=n 指定区大小。
5、总的 Region 个数最大可以存在 2048 个,即heap最大能够达到32M*2048=64G
6、0.5<obj<1,那么放到old区,old标记为H 1<obj<n,连续的n个region,作为H
过程:
初始标记:标记出GCRoot对象,以及GCRoot所在的Region(RootRegion)
Root Region Scanning:扫表整个old的Region
并发标记:并发追溯标记,进行GCRootsTracing的过程
最终标记:修正并发标记期间,因程序运行导致标记发生变化的那一部分对象
清理回收:根据时间来进行价值最大化的回收,重置rset
ZGC:Z Garbage Collector 垃圾收回器,是一种可伸缩的低延迟垃圾收集器。
逻辑上一次ZGC分为Mark(标记)、Relocate(迁移)、Remap(重映射)三个阶段
- Mark: 所有活的对象都被记录在对应Page的Livemap(活对象表,bitmap实现)中,以及对象的Reference(引用)都改成已标记(Marked0或Marked1)状态
- Relocate: 根据页面中活对象占用的大小选出的一组Page,将其中的活对象都复制到新的Page,并在额外的forward table(转移表)中记录对象原地址和新地址对应关系
- Remap: 所有Relocated的活对象的引用都重新指向了新的正确的地址
实现上,由于想要将所有引用都修正过来需要跟Mark阶段一样遍历整个对象图,所以这次的Remap会与下一次的Remark阶段合并。所以在GC的实现上是2个阶段,即Mark&Remap阶段和Relocate阶段
使用场景对比:
G1适合8/16G以上的内存使用,原因在于G1 rescan更快,清除垃圾时虽然是stop the world但是可控,
CMS虽然是并发但是不可控,大块内存要回收会影响到应用程序的性能。
另外由于G1在清理垃圾时使用STW,所以可以采用标记整理算法,没有内存碎片问题
ZGC作为下一代垃圾回收器,性能非常优秀。ZGC垃圾回收过程几乎全部是并发,实际STW停顿时间极短,不到10ms。这得益于其采用的着色指针和读屏障技术。