2018年9月份,jdk11问世。一个值得关注的地方是加入了zgc垃圾回收器。借此机会,复习一下jvm的垃圾回收器,然后看看新的zgc垃圾回收器。
1 垃圾回收器分类
- 按线程数分:串行垃圾回收器和并行垃圾回收器。串行垃圾回收器一次只使用一个线程进行垃圾回收,并行垃圾回收器一次可以开启多个线程进行回收。因此,在并行能力较强的CPU上,使用并行垃圾回收器可以缩短GC停顿时间。
- 按工作模式分。分为独占式垃圾回收器和并发式垃圾回收器。并发式垃圾回收器会与应用程序线程交替工作,以减少应用程序停顿时间。独占式垃圾回收器会stop the world,应用程序停止运行,直到垃圾回收过程完全结束。
- 按工作的内存区间划分。分为新生代垃圾回收器和老生代垃圾回收器。
- 按碎片处理方式分。可以分为压缩式垃圾回收器和非压缩式垃圾回收器。压缩式垃圾回收器在回收之后,会对存活的对象进行压缩整理,而非压缩式的不进行这一操作。
看看几种垃圾回收器的分类,如下图所示。

除了ZGC垃圾回收器以外,其他的垃圾回收器都是分代收集器。Serial、ParNew和Paralle Scavenge负责回收新生代的垃圾,采用复制算法。Serial Old、CMS和Parallel Old负责老年代的回收,Serial Old和Parallel Old采用MC(mark and compact,标记整理算法)算法,CMS(concurrent mark sweep)采用MS(mark and sweep,标记清理算法)算法来清理。G1回收器也是一个分代垃圾回收器,可以同时负责新生代和老年代的垃圾回收,新生代采用复制算法,老年代采用标记整理算法。ZGC不是一个分代垃圾回收器,下文将会介绍。
图中,新生代垃圾回收器和老年代垃圾回收器采用直线相连,表示它们可以搭配使用。当CMS垃圾回收器在运行期间没有足够的内存时,将会出现Concurrent Mode Failure的问题,此时会启动Serial Old来进行垃圾回收。
2 新生代垃圾回收器
采用复制回收算法
Serial
新生代串行收集器,串行进行垃圾回收,独占式进行垃圾回收。

优点:是一个经过长时间生产环境考验的收集器。在诸如单CPU处理器或者较小的应用内存等硬件不是特别优越的场合,它的性能表现可以超过并行(Parallel)回收器和并发(concurrent)回收器。
缺点:不能充分利用多CPU的资源
ParNew
并行收集器。并行,独占式垃圾回收。

优点:回收时,充分利用多CPU的资源。
缺点:仍然会将应用程序停顿后再回收垃圾。在单CPU上会有多线程上下文切换开销。
Parallel Scavenge
新生代并行回收 (Parallel Scavenge) 收集器,多线程,独占式。但是,关注系统的吞吐量。

优点:可以设置垃圾停顿时间和吞吐量大小,支持自适应的GC调节策略。
缺点:单CPU有线程切换开销,独占式
3 老年代
Serial Old
老年代串行收集器。采用标记-压缩算法。串行的、独占式的垃圾收集器。

优点:可以和多种新生代的垃圾回收器配合使用,可以作为CMS收集器的备用收集器。
缺点:由于老年代的回收时间通常比新生代更长,因此,应用程序的停顿时间会比较长。
Parallel Old
老年代并行回收收集器,标记-压缩算法,多线程并发的收集器,关注吞吐量。JDK1.6之后开始启用。

CMS
并发标记清除。多线程,并发式垃圾收集,采用标记-清除算法。
CMS 工作时,主要步骤有:初始标记、并发标记、重新标记、并发清除和并发重置。其中初始标记和重新标记是独占系统资源的,而并发标记、并发清除和并发重置是可以和用户线程一起执行的。因此,从整体上来说,CMS 收集不是独占式的,它可以在应用程序运行过程中进行垃圾回收。

优点:应用程序停顿时间短,可以充分利用多CPU的资源。
缺点:单CPU性能不好,线程切换开销大。可能会有大量的内存碎片,但可以设置内存碎片整理。
4 总结
这里概括了G1和ZGC之外的垃圾回收器的特点,并没有介绍具体的细节。之后将比较详细的介绍G1和ZGC。
另外,jdk7和jdk8的默认垃圾回收器都是Paralle Scavenge + Parallel Old的组合。jdk9和jdk10的默认垃圾回收器是G1。
5 参考
JVM垃圾回收器工作原理及使用实例介绍
一文了解JVM全部垃圾回收器,从Serial到ZGC
G1 垃圾收集器介绍
Java Hotspot G1 GC的一些关键技术
An Introduction to ZGC