一、Serial收集器
Serial曾经是新生代收集的唯一选择(jdk1.3.1之前),是个单线程收集器,在它进行垃圾收集的时候必须暂停其它所有的工作线程(stop the world),直到它工作结束。
优点:简单高效,在client模式下的虚拟机是个好选择。
二、ParNew收集器
parNew其实就是Serial收集器的多线程版本,除了使用多线程进行垃圾收集器之外,控制参数,收集算法、stop the world、对象分配规则、回收策略都与Serial一样。
三、Parallel Scavenge收集器
Parallel Scavenge收集器也是一个新生代收集器,它是使用复制算法的收集器,又是并行的多线程收集器,该收集器的目的并不是缩短停顿时间,而是达到一个可控制的吞吐量。这个地方的吞吐量=运行用户代码的时间/(运行用户代码的时间+垃圾收集的时间)
停顿时间越短就越适合需要和用户交互的程序,良好的响应速度能提升用户的体验;搞吞吐量则可以最高效率的利用cpu时间,尽快地完成程序的运算任务,主要适合在后台运算不需要太多交互的任务。
四、Serial old收集器
Serial Old是Serial收集器的老年代版本。它也是单线程收集器,使用标记整理算法。
优点:简单高效,在client模式下的虚拟机是个好选择。
五、parallel old收集器
parallel old收集器是Parallel Scavenge的老年代版本,使用多线程和标记整理算法。
吞吐量优先
六、CMS收集器
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收时间为目标的收集器,在重视服务的响应速度的系统上得到规模应用。
基于标记清除算法实现,四个步骤:
- 初始标记
- 并发标记
- 重新标记
- 并发清除
其中初始标记、重新标记这两个步骤依然需要“stop the world”。初始标记仅仅是记录一下GC Roots关联到的对象,速度很快,并发标记阶段就是进行GC Roots Tracing的过程,而重新标记阶段则是为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录。
CMS收集器是和用户线程并发执行的,它最大的优点是:并发收集、低停顿。
它也有三个显著的缺点:
- CMS收集器对CPU资源非常敏感。并发标记和并发清理的同时,让GC与用户线程交替执行,尽量减少GC线程独占资源的时间,这样垃圾收集的时间会更长,但对用户线程影响就会小一些。
- CMS收集器无法处理浮动垃圾。
- 是因为标记清除算法的问题,会产生大量的内存碎片。
七、G1收集器
G1收集器是垃圾收集器理论进一步的产物,有两点改进:
- G1收集器是基于标记-整理算法实现的收集器,也就是说它不会产生内存碎片。
- 它可以非常精准的控制停顿,既能让使用者明确指定一个长度为M毫秒的时间片段内,消耗在垃圾收集的时间不得超过N秒
G1算法是将整个堆(包括新生代、老年代)分为多个大小不同的独立区域(Region),并且跟踪这些区域里面的垃圾堆积程度,在后台维护一个优先列表,每次根据允许的收集时间,优先回收垃圾最多的区域。
八、ZGC收集器
Z Garbage Collector
停顿时间不会超过10ms
停顿时间不会随着堆的增大而增大(不管多大的堆都能保持在10ms以下)
可支持几百M,甚至几T的堆大小(最大支持4T)
- ZGC只有短暂的STW,大部分的过程都是和应用线程并发执行,比如最耗时的并发标记和并发移动过程。
- ZGC中没有新生代和老年代的概念,只有一块一块的内存区域page,以page单位进行对象的分配和回收。
- 每次进行GC时,都会对page进行压缩操作,所以完全避免了CMS算法中的碎片化问题。
- 现在多CPU插槽的服务器都是Numa架构,比如两颗CPU插槽(24核),64G内存的服务器,那其中一颗CPU上的12个核,访问从属于它的32G本地内存,要比访问另外32G远端内存要快得多。ZGC默认支持NUMA架构,在创建对象时,根据当前线程在哪个CPU执行,优先在靠近这个CPU的内存进行分配,这样可以显著的提高性能,在SPEC JBB 2005 基准测试里获得40%的提升。