2.1 垃圾回收器发展历史

有了虚拟机,就一定需要收集垃圾的机制,这就是 Garbage Collection,对应的产品我们称为 Garbage Collector。

  • 1999年随JDK1.3.1一—起来的是串行方式的 Seria1GC,它是第一款GC。 Pardew垃圾收集器是 Seria1收集器的多线程版本。
  • 2002年2月26日,Parallel GC和 Concurrent Mark Sweep GC跟随JDK1.4.2一起发布。
  • Parallel GC在JDK6之后成为 Hot Spot默认GC。
  • 2012年,在JDK1.7u4版本中,G1可用。
  • 2017年,JDK9中G1变成默认的垃圾收集器,以替代CMS。
  • 2018年3月,JDK10中G1垃圾回收器的并行完整垃圾回收,实现并行性来改善最坏情况下的延迟。
  • 2018年9月,JDK11发布。引入Epsilon垃圾回收器,又被称为”No-Op(无操作)回收器。同时,引入ZGC: 可伸缩的低延迟垃圾回收器( Experimental)。
  • 2019年3月,JDK12发布。增强G1,自动返回未用堆内存给操作系统。同时,引入Shenandoah GC:低停顿时间的GcC( Experimental)。
  • 2019年9月,JDK13发布。增ZGC,自动返回未用堆内存给操作系统。
  • 2020年3月,JDK14发布。删除CMS垃圾回收器。扩展ZGC在 macOs和 Windows上的应用。

    2.2 7款经典的垃圾收集器

  • 串行回收器: serial、serial old

  • 并行回收器: ParNew、Parallel Scavenge、Parallel old
  • 并发回收器:CMS、G1

image.png

2.3 7款经典垃圾收集器与垃圾分代之间的关系

image.png

  • 新生代收集器: Serial、ParNew、Parallel scavenge;
  • 老年代收集器: Serial Old、Parallel Old、CMS;
  • 整堆收集器:G1;

垃圾收集器的组合关系
image.png
此图已经更新到jdk14.

  • CMS GC不是老年代满了回收,是提前回收,因为是并发的,同时用户线程还在执行,有可能会制造出新的垃圾。如果回收的比较晚或者垃圾的制造速度比回收速度要快,就会出现回收失败的情况,如果失败,就会将Serial Old GC(MSC)作为一个后备方案,触发full GC 将用户线程停下来进行垃圾回收。
  • jdk9中红色的虚线是被移除的方案

1.两个收集器间有连线,表明它们可以搭配使用:
serial/serial old、seria1/CNS、ParNew/Serial old、ParNew/CMS、Parallel Scavenge/Serial 0ld、Parallel Scavenge/Parallel old、G1;
2.其中serial old作为CMS出现”concurrent Mode Failure”失败的后备预案。
3.(红色虚线)由于维护和兼容性测试的成本,在JDK 8时将serial+CMS、ParNew+Serial old这两个组合声明为废弃(JEP 173),并在JDK 9中完全取消了这些组合的支持(了EP214),即:移除。
4.(绿色虚线)JDK 14中:弃用Parallel Scavenge和Serial0ld GC组合(JEP 366)
5.(青色虚线)JDK 14中:删除CMS垃圾回收器(JEP 363)

2.4 不同的垃圾回收器概述

  • 为什么要有很多收集器,一个不够吗?因为Java的使用场景很多,移动端,服务器等。所以就需要针对不同的场景,提供不同的垃圾收集器,提高垃圾收集的性能。
  • 虽然我们会对各个收集器进行比较,但并非为了挑选一个最好的收集器出来。没有一种放之四海皆准、任何场景下都适用的完美收集器存在,更加没有万能的收集器。所以我们选择的只是对具体应用最合适的收集器。

查看默认的垃圾回收器

  • —XX:+PrintCommandLineFlags: 查看命令行相关参数(包含使用的垃圾收集器)
  • 使用命令行指令:jinfo -flags 相关垃圾回收器参数进程ID