如果说垃圾收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现,这里讨论一下基于JDK1.7 之后的HotSpot 虚拟机所包含的垃圾收集器,先来一张图:
JVM垃圾收集器

这张图中两个收集器之间存在的连线,就说明他们可以搭配使用,虚拟机所处的区域,则表示他是属于新生代收集器还是老年代
收集器。

从JDK1.3之前都在用Serial收集器,一直到现在JDK 1.7,HotSpot 虚拟机开发团队为消除或者减少工作线程因内存回收儿导致停顿的努力一在进行着,从Serial收集器到Parallel收集器
再到ConcurrentMarkSweep (CMS ) 乃至GC收集器最前沿的成果Garbage First (G1) 收集器,一直致力于用户线程的停顿时间不短缩短,但是依旧没有办法完全消除。

1.  Serial 收集器
                Serial 收集器是最基本,发展历史最悠久的收集器,曾经在JDK1.3之前是虚拟机新生代收集的唯
一选择。他是一个单线程的收集器,在他进行垃圾收集的时候,必须暂停其他所有的工作线程,直到它收集结束。
Stop The World 是对它的一个最好的描述了,下图是Serial收集器的运行过程:

JVM垃圾收集器

但是他依然是虚拟机在Client模式下的默认新生代收集器,他也有着优于其他收集器的地方:简单而高效(与其他单线程的收集器相比) ,对于限定单个CPU的环境来说,Serial收集器由于没有线程
交互的开销,自然可以提高单线程收集效率。所以Serial收集器对于运行在Client模式下的虚拟机来说是一个很好的选择。

2. PraNew收集器

他是Serial收集器的多线程版本,除了使用多线程进行垃圾收集之外,其余包括收集算法,Stop The World ,对象分配规则,回收策略等都与Serial 收集器完全一样。
下图是PraNew收集器的工作过程:
JVM垃圾收集器
目前只有它能和CMS收集器配合工作,ParNew 收集器也是使用-XX:+UseConcMarkSweepGC 选项后的默认新生代收集器,也可以使用-XX:UsePraNewGC选项强制指定他。
他默认开启的收集线程数量与CPU的数量相同,在CPU非常多的环境下,可以使用-XX:ParallelGCThreads参数来限制垃圾收集的线程数。

3. Parallel Scavenge 收集器

Parallel Scavenge 收集器是一个新生代收集器,他也是使用复制算法的收集器,又是并行的多线程收集器。Parallel Scavenge 收集器的特点是他的两个关注点与其他的收集器不同
,CMS收集器关注点是尽可能缩短卡机收集器时候,用户线程的停顿时间,而Parallel Scavenge 收集器的目的是达到一个可控制的吞吐量。
吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集时间)
主要适合在后台运算而不需要太多交互的任务。
Parallel Scavenge 收集器提供了两个参数用于精确控制吞吐量,分别是:控制最大垃圾收集停顿的时间(-XX:MaxGCPauseMilis)参数以及直接设置吞吐量大小(-XXGCTimeRatio)参数
不过大家不要认为如果把“最大垃圾收集停顿的时间”参数设置小一点就可以使得垃圾收集速度变得更快,GC停顿时间缩短是以牺牲吞吐量和新生代空间来换取的。

4.Serial Old 收集器

Serial Old 是Serial收集器的老年代版本,他同样是个单线程收集器,使用“标记整理”算法。这个收集器的主要意义也是给Client模式下的虚拟机使用。
Serial Old 收集器的运行示意图如下:
JVM垃圾收集器

5. Parallel Old 收集器

Parallel Old 是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。他是在JDK1.6才开始提供的,在此之前,新生代的Parallel Scavenge收集器一直处于
比较尴尬的状态,原因是,如果新生代选择了Parallel Scavenge 收集器,老年代除了Serial Old 收集器之外别无选择。由于老年代Serial Old 收集器在服务端应用性能上的“拖累"
使用了Parallel Scavenge 收集器也未必能在整体应用上 获得吞吐量最大的效果,由于单线程的老年代收集中无法充分利用服务器多CPU的处理能力,在老年代很大而且硬件
比较高级的环境中,这种组合的吞吐量甚至还不一定有ParNew 加上CMS的组合给力。直到Parallel Old 收集器出现后,吞吐量有线收集器终于有了名副其实的组合,在注重吞吐量以及
CPU资源敏感的场合,都可以有线考虑Parallel Scavenge 加Parallel Old 收集器,Parallel Old 收集器工作过程如图:
JVM垃圾收集器

6. CMS 收集器

CMS(Concurrent Mark Sweep) 收集器是一种以获最短回收停顿时间为目标的收集器。从名字(Mark Sweep )上就可以看出,CMS 是基于“标记-清除”算法 实现的,他的运作过程相对于
前面几种收集器来说更复杂一些,整个过程分为4个步骤:

  • 初始标记(CMS initial mark)
  • 并发标记(CMS concurrent mark)
  • 重新标记(CMS remark)
  • 并发清除(CMS concurrent sweep)

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

JVM垃圾收集器

7. G1 收集器

G1 是一款面向服务端应用的垃圾收集器,HotSpot 开发团队赋予他的使命是未来可以替换JDK1.5中的CMS收集器,G1 具备以下特点:

  • 并行与并发:G1 能充分利用多CPU,多核环境下的硬件优势,使用多个CPU来缩短Stop The World 停顿的
    时间部分其他收集器原本需要停顿Java线程执行的GC动作,G1收集器仍然可以通过并发的方式让Java程序继
    续执行。

    • 分代收集:他能够采用不同的方式去处理新创建的对象和已经存活了一段时间,熬过多次GC的就对象以获取
      更好的收集效果。
    • 空间整合:与CMS的标记清除算法不同,G1从整体看来是基于 标记-整理算法实现的,但从局部看来基于复
      制算法实现的。但无论如何,这两种算法都意味着G1运作期间不会产生内存空间碎片,手机后能提供规整的
      可用内存。
    • 可预测的停顿:G1 还能建立可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,
      消耗在垃圾收集上的时间不得超过N毫秒。

      G1 收集器运行示意图如下:

JVM垃圾收集器