垃圾收集器

经典收集器之间的关系

+-----------------------+-----------------------+
| Young Generation      |                       |
|        +------+       |       +---+           |
|        |Serial|-------+-+-----|CMS|           |
|        +------+       |  \   /+---+           |
|                       |    x                  |
|        +------+       |  /   \+----------+    |
|        |ParNew|-------+-+-----|Serial Old|    |
|        +------+       |      /+----------+    |
|                       |    /                  |
|      +--------+       |  /    +------------+  |
|      |Parallel|-------+-+-----|Parallel Old|  |
|      |Scavenge|       |       +------------+  |
|      +--------+    +------+                   |
|                    |  G1  |                   |
|                    +------+                   |
|                       |    Tenured Generation |
+-----------------------+-----------------------+

新生代

Serial 收集器

Serial 收集器是一个单线程工作的收集器,它在进行垃圾回收时,必须暂停其它所有工作线程,直到垃圾回收结束。

Serial 收集器适用于运行在客户端模式或者是单核处理器下的虚拟机。

ParNew 收集器

ParNew 收集器实质上是 Serial 收集器的多线程并行版本。

ParNew 收集器默认开启的收集器线程数与处理器核心数量相同,在处理器核心非常多的环境中,可以使用参数 -XX:ParallelGCThreads 来限制垃圾收集的线程数。

Parallel Scavenge 收集器

Parallel Scavenge 收集器关注的目标是垃圾回收的吞吐量,被称为「吞吐量优先收集器」。

Parallel Scavenge 收集器提供了两个参数用于精确控制吞吐量大小的:

  • -XX:MaxGCPauseMillis 控制最大垃圾回收的停顿时间;

  • -XX:GCTimeRatio 直接设置吞吐量大小。

Parallel Scavenge 收集器还提供了一个参数 -XX:UseAdaptiveSizePolicy,用于指示虚拟机根据当前系统运行的情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量。这种调节方式被成为垃圾收集器的自适应调节策略。

老年代

Parallel Old 收集器

Parallel Old 是 Parallel Scavenge 收集器的老年代版本。

CMS 收集器

CMS(Concurrent Mark Sweep)收集器是一种以获取最短停顿时间为目标的收集器。

CMS 收集器基于标记 - 清除算法实现,整个过程分为四个步骤:

  1. 初始标记(CMS initial mark),仅标记 GC Roots 能直接关联到的对象,速度很快;

  2. 并发标记(CMS concurrent mark),从 GC Roots 直接关联的对象开始遍历整个对象图,过程比较长但是不需要停顿工作线程,可以与垃圾收集线程一起并发运行;

  3. 重新标记(CMS remark),修正并发标记阶段期间,因为工作线程继续运行而导致标记产生变动的那一部分对象的标记记录;

  4. 并发清除(CMS concurrent sweep),清理删除标记阶段判断为已经死亡的对象。

CMS 收集器存在以下三个明显的缺点:

  1. 对处理器资源非常敏感,CMS 默认启动的回收线程数是(核心处理数 + 3)/ 4;

  2. 无法处理浮动垃圾(Floating garbage);

  3. 产生大量的空间碎片。

Mixed GC

Garbage First 收集器

在 G1(Garbage First) 收集器出现之前的所有其它收集器,垃圾收集的目标范围要么是整个新生代(Minor GC),要么是整个老年代(Major GC),再要么就是整个 Java 堆(Full GC)。G1 可以面向堆内存里的任何部分来组成回收集(Collection Set,CSet)进行回收。

G1 不再以固定大小以及固定数量的分代区域划分,而是把连续的 Java 堆分成多个大小相等的独立区域(Region),每一个 Region 都可以根据需要被设置为新生代的 Eden 空间、Survivor 空间或者是老年代空间。G1 收集器能够对不同角色的 Region 采用不同的处理策略。

Region 中有一类特殊的 Humongous 区域,专门用来存储大对象的。G1 认为只要大小超过了一个 Region 容量的一般的对象,即可判定为大对象。每个 Region 的大小可以通过参数 -XX:G1HeapRegionSize 设定,取值范围为 1MB~32MB,且应是 2 的 N 次幂。对于那些超过了整个 Region 容量的超级大对象,将会被存放在 N 个连续的 Humongous Region 之中,G1 的大多数行为都会把 Humongous Region 作为老年代的一部分来进行看待。

G1 收集器能建立可预测的停顿时间模型,它将 Region 作为单次回收的最小单元,即每次收集的内存空间都是 Region 大小的整数倍。G1 收集器会跟踪各个 Region 中的垃圾堆积的「价值」大小,价值即回收所获得的空间大小以及回收所需要时间的经验值,然后维护一个优先级列表,每次根据用户设定的收集停顿时间(使用 -XX:MaxGCPauseMillis 指定,默认值是 200ms)优先处理回收价值收益最大的那些 Region,这也就是 Garbage First 名字的由来。

G1 收集器 使用 Region 划分内存空间,以及 具有优先级的区域回收方式,保证 G1 收集器在有限的时间内获得尽可能高的收集效率。

+-+-+-+-+-+-+-+-+-+-+
|E| | |S| | | | |E| |
+-+-+-+-+-+-+-+-+-+-+
| | | | | |E| | | | |
+-+-+-+-+-+-+-+-+-+-+
| | |E| | | |E| | |E|
+-+-+-+-+-+-+-+-+-+-+
|E| | | | | | | |E| |
+-+-+-+-+-+-+-+-+-+-+
| | |E| |E| | | | | |
+-+-+-+-+-+-+-+-+-+-+
| |S| | |S| | |H|H| |
+-+-+-+-+-+-+-+-+-+-+
| | | | | | | |H| | |
+-+-+-+-+-+-+-+-+-+-+
| | | | | |H| | | | |
+-+-+-+-+-+-+-+-+-+-+

最后更新于