深入理解JVM(4)--- 垃圾收集器

如果说收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。

垃圾收集器

HotSpot虚拟机的垃圾收集器

新生代垃圾收集器

1. Serial收集器

  • 单线程收集器
  • Stop The World:
    它不仅只会使用一个cpu或一条收集线程去完成垃圾收集工作,而且在进行垃圾收集时,必须暂停其他所有的工作线程,直到它收集结束。
  • 是虚拟机运行在Client模式下的默认新生代收集器
  • 简单高效(与其他收集器的单线程比)

Serial收集器运行示意图

2. ParNew收集器

  • 是Serial收集器的多线程版本:除了使用多条线程进行垃圾收集之外,其余行为包括Serial收集器可用的所有控制参数、收集算法、Stop The World、对象分配规则、回收策略等都与Serial收集器完全一样。
  • 是许多运行在Server模式下的虚拟机中首选的新生代收集器
  • 除了Serial收集器外,目前只有它能与CMS收集器配合工作
  • 它默认开启的收集线程数与CPU的数量相同

ParNew收集器运行示意图

3. Parallel Scavenge收集器

Parallel Scavenge收集器是新生代、使用复制算法的并行多线程收集器。它无法与CSM收集器搭配使用

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

【注】停顿的时间越短就越适合需要用户交互地程序,良好的响应速度能提升用户体验,而高吞吐量则可以高效率地利用CPU时间,尽快完成程序的运算任务,主要适合后台运算而不需要太多交互地任务。

Parallel Scavenge收集器提供了两个参数用于精确控制吞吐量,分别是控制最大垃圾收集停顿时间的-XX:MaxGCPauseMillis以及直接设置吞吐量大小的-XX:GCTimeRatio参数

GC停顿时间缩短是以牺牲吞吐量和新生代空间来换取的。

老年代垃圾收集器

4. Serial Old收集器

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

如果在Server模式下,它还有两大用途:

  1. 在JDK1.5以及之前的版本中与Parallel Scavenge收集器搭配使用
  2. 作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure时使用。

Serial Old收集器运行示意图

5. Parallel Old收集器

Parallel Old收集器是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法,在JDK1.6中才开始提供。

Parallel Old收集器运行示意图

6. CMS收集器

CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。基于“标记-清除”算法,整个工作过程分为四步:

  1. 初始标记(CMS inital mark)
  2. 并发标记(CMS concurrent mark)
  3. 重新标记(CMS remark)
  4. 并发清除(CMS concurrent sweep)

其中,初始标记、重新标记这两个步骤仍需“Stop The World”,初始标记仅仅只是标记一下GC Roots能直接关联到的对象,速度很快,并发标记阶段就是进行GC Roots Tracing的过程,而重新标记阶段则是为了修正并发标记期间因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。

由于整个过程中耗时最长的并发标记和并发清除过程收集器线程都可以与用户线程一起工作,所以,从总体来说,CMS收集器的内存回收过程是与用户线程一起并发执行的。

CMS收集器运行示意图

7. G1收集器(新生代和老年代通用)

未完待续……