JVM 垃圾回收器分类

1. 前言

本节主要讲解 7 种垃圾回收器,其中有 3 种垃圾回收器是作用于年轻代垃圾回收的收集器;另外 3 种圾回收器是作用于老年代垃圾回收的收集器;剩余的 1 种垃圾回收器能够同时作用于年轻代和老年代。

7 种垃圾回收器以及其作用的内存区域如下图所示:

图片描述

通篇皆为重点知识,请认真学习并理解每种垃圾回收器的特点。

2. Serial收集器

基本概念:Serial收集器是最基本、发展历史最久的收集器,这个收集器是采用复制算法的单线程的收集器。

Tips:从概念上来看,我们需要注意Serial收集器的两个特点:一个是采用复制算法,另外一个是单线程收集。

单线程的收集器:单线程一方面意味着他只会使用一个 CPU 或者一条线程去完成垃圾收集工作,另一方面也意味着他进行垃圾收集时必须暂停其他线程的所有工作,直到它收集结束为止。

不过实际上到目前为止,Serial收集器依然是虚拟机运行在 Client 模式下的默认新生代收集器,因为它简单而高效。Serial 收集器运行过程如下图所示:

图片描述

3. Parnew收集器

基本概念:Parnew 收集器其实就是Serial收集器的多线程版本,除了使用多线程进行垃圾收集外,其余行为和 Serial 收集器完全一样,但是他却是 Server 模式下的虚拟机首选的新生代收集器。

Tips:从概念上来看,我们需要注意Parnew收集器的两个特点:一个是采用复制算法,另外一个是多线程收集。

特点

  • 除了 Serial 收集器外,目前只有它能与 CMS 收集器配合工作。CMS 收集器第一次实现了让垃圾收集器与用户线程基本上同时工作;
  • Parnew 收集器默认开启的收集线程数与 CPU 数量相同,在 CPU 数量非常多的情况下,可以使用 -XX:ParallelGCThreads 参数来限制垃圾收集的线程数。

Parnew 收集器运行过程如图所示:

图片描述

4. Parallel Scavenge收集器

基本概念:Parallel Scavenge 收集器也是一个新生代收集器,也采用了复制算法,也是并行的多线程收集器。Parallel Scavenge 收集器的目标是达到一个可控制的吞吐量。Parallel Scavenge 收集器是虚拟机运行在 Server 模式下的默认垃圾收集器。被称为“吞吐量优先收集器”。

Tips:从概念上来看,我们需要注意Parallel Scavenge收集器的三个个特点:一个是采用复制算法,一个是多线程收集,一个是达到控制吞吐量的目标。

Parallel Scavenge 收集器运行过程同 Parnew 收集器一样:

图片描述

控制吞吐量:CMS 等收集器的关注点是尽可能缩短垃圾收集时用户线程的停顿时间,而 Parallel Scavenge 收集器的目标则是达到一个可控制的吞吐量。所谓吞吐量就是 CPU 用于运行用户代码时间与 CPU 总消耗时间的比值,即吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)

空间吞吐量参数介绍:虚拟机提供了-XX:MaxGCPauseMills-XX:GCTimeRatio 两个参数来精确控制最大垃圾收集停顿时间和吞吐量大小。不过不要以为前者越小越好,GC 停顿时间的缩短是以牺牲吞吐量和新生代空间换取的。由于与吞吐量关系密切,Parallel Scavenge 收集器也被称为“吞吐量优先收集器”。

Parallel Scavenge 收集器有一个参数 -XX:UseAdaptiveSizePolicy 参数,这是一个开关参数,这个参数打开之后,就不需要手动指定新生代大小、Eden 区和 Survivor 参数等细节参数了,虚拟机会根据当前系统的运行情况以及性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量。

如果对于垃圾收集器运作原理不太了解,以至于在优化比较困难的时候,可以使用 Parallel Scavenge收集器配合自适应调节策略,把内存管理的调优任务交给虚拟机去完成。

5. Serial Old收集器

基本概念: Serial Old 收集器同样是一个单线程收集器,作用于老年代,使用“标记-整理算法”,这个收集器的主要意义也是在于给 Client 模式下的虚拟机使用。

Serial Old 收集器运行过程如图所示:

图片描述

6. Parallel Old收集器

基本概念: Parallel Old 收集器是 Parallel Scavenge 收集器的老年代版本,使用多线程和“标记-整理算法”进行垃圾回收。

这个收集器在 JDK 1.6 之后的出现,“吞吐量优先收集器”终于有了比较名副其实的应用组合,在注重吞吐量以及 CPU 资源敏感的场合,都可以优先考虑 Parallel Scavenge收集器+Parallel Old收集器 的组合。

Parallel Scavenge 收集器+Parallel Old 收集器 的组合运行过程如下图所示:

图片描述

7. CMS收集器

基本概念:CMS(Conrrurent Mark Sweep,连续标记扫描)收集器是以获取最短回收停顿时间为目标的收集器。使用标记-清除算法。

收集步骤:收集过程分为如下四步:

  • 初始标记:标记 GCRoots 能直接关联到的对象,时间很短;
  • 并发标记:进行 GCRoots Tracing(可达性分析)过程,时间很长;
  • 重新标记:修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,时间较长;
  • 并发清除:回收内存空间,时间很长。其中,并发标记与并发清除两个阶段耗时最长,但是可以与用户线程并发执行。

CMS 收集器运行过程如下图所示:

图片描述

8. G1收集器

基本概念:G1 是目前技术发展的最前沿成果之一,HotSpot开发团队赋予它的使命是未来可以替换掉 JDK1.5 中发布的 CMS 收集器。

与其他GC收集器相比,G1收集器具有以下特点

  • 并发和并行:使用多个 CPU 来缩短 Stop The World 停顿时间,与用户线程并发执行;
  • 分代收集:独立管理整个堆,但是能够采用不同的方式去处理新创建对象和已经存活了一段时间、熬过多次 GC 的旧对象,以获取更好的收集效果;
  • 空间整合:基于标记-整理算法,无内存碎片产生;
  • 可预测的停顿:能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为 M 毫秒的时间片段内,消耗在垃圾收集器上的时间不得超过N毫秒。

在G1之前的垃圾收集器,收集的范围都是整个新生代或者老年代,而 G1 不再是这样。使用 G1 收集器时,Java 堆的内存布局与其他收集器有很大差别,它将整个Java堆划分为多个大小相等的独立区域(Region),虽然还保留有新生代和老年代的概念,但新生代和老年代不再是物理隔离的了,它们都是一部分(可以不连续)Region 的集合。

9. 小结

本节主要讲解了 7 种垃圾收集器:Serial 收集器,Parnew 收集器,Parallel Scavenge 收集器,Serial Old 收集器,Parallel Old 收集器,CMS 收集器和G1 收集器。

其中专门针对年轻代的收集器有 Serial 收集器,Parnew 收集器和 Parallel Scavenge 收集器;专门作用于老年代的收集器有Serial Old 收集器,Parallel Old 收集器和 CMS 收集器;而 G1 收集器即能够作用于年轻代,也能够作用于老年代。

学习者需要对这 7 种垃圾回收器进行理解,并掌握其作用的内存区域。