- Serial/Serial Old 收集器
这是两款最基本的垃圾回收器,一般用于客户端模式下,适合单核或者配置较低的情况。
Serial:新生代垃圾收集器,标记复制算法,单个垃圾收集线程,会产生Stop The World
Serial Old:老年代垃圾收集器,标记-整理算法,单个垃圾收集线程,Stop The World,可作为CMS收集器并发失败时的后备预案
- Par New / Parallel Old 收集器
相比于Serial/Serial Old,这两款垃圾收集器也很类似,主要区别是引入了多个垃圾收集线程,但收集的时候仍然是需要Stop The World的,无法与用户线程并发
Par New :新生代垃圾收集器,标记复制算法,多个垃圾收集线程,Stop The World,经常与CMS垃圾收集器搭配使用
Parallel Old:老年代垃圾收集器,标记整理算法,多个垃圾收集线程,Stop The World,与Paralle Scavenge收集器搭配使用
- Parallel Scavenge收集器
新生代垃圾收集器,与Parallel Old搭配使用,与Par New 类似,采用多个垃圾收集线程,会产生Stop The World,但是相对于Par New,它有着一些独特的特点,优势
首先它是一款以吞吐量优先的垃圾收集器,可以通过-XX:GGTimeRatio,来达到设置吞吐量的目的。另一个特点是它有一个自适应调节策略,可通过-XX:UseAdaptiveSizePolicy这个开关参数开启自适应调节,开启后它将自动调节新生代大小,Eden与Survivor的比例,晋升老年代对象大小等参数值,从而尽量满足设置的吞吐量参数或者停顿时间参数
- CMS(Concurrent Mark Sweep)收集器
老年代垃圾收集器,与Par New搭配使用。它是一款以最小回收停顿时间优先的垃圾收集器,也是Hotspot第一款真正采用并发收集算法的垃圾收集器。采用了标记-清除算法,在标记阶段利用增量更新解决并发标记问题。其缺点也很明显,会产生大量的内存碎片,且吞吐量也不高。在进行Full GC时会对内存碎片利用整理算法进行整理(会Stop The World)。并发清除阶段可能用户线程会没有足够的内存空间分配对象,导致分配失败,此时会以Serial Old收集器作为分配失败的后备预案(会Stop The World)
- G1(Garbage First)收集器
以CMS收集器替代者的身份出现,同样以最小回收停顿时间为目标,是JDK9的默认垃圾收集器(JDK8是Parallel Scanvenge + Parallel Old组合)。它开创了以局部收集思想和面向Region的内存布局,以Region做为最小回收单元,多个Region组成回收机CSet。同样,这款垃圾收集器中也包含着分代收集思想,不过不同于之间的收集器将堆内存划分为新生代,老年代的布局。G1将堆空间按固定大小(1M-32M可通过启动参数设定)划分为多个Region,每个Region都可以根据需要作为新生代(Eden,Survivor),老年代(Old),或者说大对象(Humongous,大小超过Region一半,当做老年代对待)
G1的特点是建立了停顿时间模型:在M毫秒的时间片内 消耗在垃圾收集上的时间不超过N毫,通过启动参数+XX:MaxGCPauseMillis可指定最大停顿时间
实现原理:在垃圾收集过程中,记录每个Region回收耗时等信息,计算出平均值,标准偏差,置信度等统计信息,从而预测出由哪些Region组成的回收集才可以在不超过设置的停顿时间约束下获得最高的收益。
G1的收集过程如上图所示。其主保证并发标记正确性的解决方案是原始快照(SATB,区别于CMS的增量更新),在筛选回收阶段更新Region统计数据,根据回收价值排序,选择回收集,回收。所以从整体上看,G1还是基于标记-整理算法的,只实现了标记阶段的与用户线程并发,回收阶段还是要Stop The World。这种方式导致其没有内存碎片问题。但如果能实现其整理阶段的并发,速度就更快了(其实,整理阶段的并发实现还是比价难得,在后来的Shenandoah和ZGC收集器便实现了整理阶段的并发)
- Shenandoah收集器
这是一款低延迟垃圾收集器,其目标是在尽可能对吞吐量影响不大的前提下,实现在任何堆内存大小下都可以把垃圾收集时间限制在10ms以内。它是OpenJDK12正式特性之一,和G1收集器有很多相似之处,甚至公用了一部分源代码。相比之下,它有许多的改进点。比如实现了并发的整理算法,用连接矩阵替代了G1的记忆集。要实现并发整理却有一个非常大的难点:与用户线程并发的情况下移动对象,用户线程可能在收集线程移动过程中对被移动的对象进行读写访问。Shenandoah采取的解决方案是读屏障+转发指针
读屏障:可以理解为虚拟机层面对对象访问操作的AOP切面,说白了就是在访问对象之前要干点什么事;转发指针:在原有对象布局结构的最前面统一加一个引用字段,在不处于并发移动的情况下,该引用指向对象自己。当对象有了一份新的副本时,只需修改该引用值指向新的副本,虚拟机对旧对向的访问就会转发到新对象上去
- ZGC收集器
它也是一款低延迟收集器,目标同Shenandoah一样,从目前的表现来看,比Shenandoah更强大,是JDK11发布的一款垃圾收集器。它的特点是Region具有动态性—动态创建和销毁,动态的区域容量大小。此外它同样实现了并发的整理算法。其实现方案是:染色指针+多重映射
染色指针:将少量额外的信息直接存储在指针上,在64位操作系统中,Linux系统只支持46位的物理地址空间(64TB),染色指针将这46位中的4位拿出来存储4个标志信息:如对象的三色标记状态、是否进入重分配集(被移动过)等信息;多重映射:由于处理器可不认识地址中哪几位是真是的寻址地址,哪几位是标记位,所以Hotspot就通过多重映射技术对地址做一个映射,将寻址地址相同,标记位不同的引用都映射到同一块物理地址空间上。
ZGC收集器仅从引用上就可以判断一个对象是否处于重分配集中(回收集),若用户访问了重分配集中的对象,将被内存屏障截获,然后根据Region上的转发表将请求转发到新复制的对象上,同时修正引用值,使其指向新对象。