常见JVM垃圾收集器一览

2016-12-31  本文已影响95人  泊浮目

在本文将会简单的介绍JVM中的常见垃圾收集器。

新生代

Serial收集器

最基本、发展历史最悠久的收集器。看上去没什么用,但实际上到现在为止,它依然是虚拟机运行在Client模式下的默认新生代收集器

特点:

  1. 单线程的收集器,说明它只会使用一个CPU或一条收集线程去完成垃圾收集工作
  2. 在它进行垃圾收集时,必须暂停其他所有的工作线程(Sun将这件事情称之为“Stop The World”),直到它收集结束。这项工作实际上是由虚拟机在后台自动发起和自动完成的,在用户不可见的情况下把用户的正常工作的线程全部停掉,这对很多应用来说都是难以接受的。

收集算法:采用复制算法

ParNew收集器

ParNew收集器其实就是Serial收集器的多线程版本,除了使用多条线程进行垃圾收集之外,其余行为都与Serial收集器完全一样,实现上这两种收集器也共用了相当多的代码。运行在Server模式下的虚拟机中。

特点:

  1. 多线程GC(并行):ParNew是Serial的多线程版本,两者共用了许多代码。
  2. 在GC时暂停所有用户线程

收集算法:采用复制算法

Parallel Scavenge收集器

在后台运算而不需要太多交互的任务。

特点:

参数:用于精确控制吞吐量

算法:采用复制算法

老年代收集器

Serial Old收集器

运行在Client模式下的虚拟机中的老年代。在Server模式下,它主要还有两大用途:

特点:

算法:采用标记-整理算法

Parallel Old收集器

运行在Server模式下的虚拟机中。在注重吞吐量及CPU资源敏感的场合,都可以优先考虑Parallel Scavenge加Parallel Old收集器。

特点

算法:采用标记-整理算法

CMS(Concurrent Mark Sweep)收集器:

Hotspot上第一个真正意义上的并发收集器。MS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目标的收集器。目前很大一部分的Java应用都集中在互联网站或B/S系统的服务端上,这类应用尤其重视服务的响应速度,希望系统停顿时间最短,以给用户带来较好的体验。往往运行在Server模式下的虚拟机中的老年代,适合对响应时间要求高的应用。

特点: 多线程 并发

过程:

  1. 初始标记:暂停用户线程,标记GC Roots能直接关联的对象,速度很快
  2. 并发标记:用户线程与标记线程并发,进行GC Roots Tracing的过程
  3. 重新标记:为了修正并发标记期间,因用户程序继续运作而导致标记产生变动的那一部分对象的标记记录,这个阶段的停顿时间一般会比初始标记阶段稍长一些,但远比并发标记的时间短。
  4. 并发清除:用户线程与清除线程并发。

缺点:

  1. 对CPU资源非常敏感。
  1. 无法处理浮动垃圾,可能出现“Concurrent Mode "Failure"失败而导致另一次Full GC的产生。

    • 浮动垃圾:在并发清除阶段,用户线程仍在运行,此时产生的垃圾无法在该次收集中处理。
    • 同时由于要保证并发,就必须预留内存给用户线程使用,因此CMS无法等到老年代几乎完全填满时再进行收集。JDK 1.5中CMS默认当老年代被使用68%时被激发。1.6中为92%。
    • 当CMS运行期间预留的内存无法满足程序需要,就会出现一次“Concurrent Mode "Failure"失败,这时虚拟机将启动后备预案:临时使用Serial Old收集器来重新进行老年代垃圾收集,这样停顿时间就会很长。
  2. 产生空间碎片,影响大对象的分配。

    • 这是由于该收集器是由“标记-清除”算法实现的所引起的。所以往往存在有很大空间剩余,当无法找到足够大的连续空间来分配当前对象,不得不提前出发一次Full GC。

    • 解决:

      1. -XX:+UseCMSCompactFullCollection 开关参数(默认开启)用于当CMS要进行Full GC时开启内存碎片的合并整理过程,该过程不能并发,故停顿时间变长。
      2. -XX:CMSFullGCsBeforeCompaction 用于设置执行多少次不压缩的Full GC后跟着来一次带压缩的Full GC。默认为0,表示每次进入Full GC时都进行碎片整理。
    • 搭配:Serial或ParNew

新生代和老年代均适用

G1收集器

面向服务端应用,适用于新生代和老年代。当前收集器技术发展的最前沿成果。

特点:

  1. 并行+并发。可充分利用CPU资源
  2. 分代收集。
  3. 空间整合。 G1从整体看是”标记-整理“算法,从局部(两个Region之间)看,是”复制“算法。 不会产生空间碎片。
  4. 可预测的停顿。建立可预测的态度时间模型,能让使用者明确指定在一个长度为M毫秒的时间内,消耗在垃圾收集的时间不得超过N毫秒,这几乎已经是实时Java(RTSJ)的垃圾收集器的特征了。

Garbage First名称的由来

G1收集器可以实现在基本不牺牲吞吐量的前提下完成低停顿的内存回收,这是由于它能够极力地避免全区域的垃圾收集。G1将内存划分为Region,跟踪各个Region里面的垃圾堆积的价值大小(回收所获得的空间大小以及回收所需时间的经验值),在后台维护一个优先列表,每次根据允许的收集时间,优先回收价值最大的Region。

过程(与CMS相似)

  1. 初始标记:暂停用户线程,标记GC Roots能直接关联的对象
  2. 并发标记:用户线程与标记线程并发,进行GC Roots的Trace
  3. 最终标记修正并发标记阶段,因用户线程继续运行而导致标记产生变动的那一部分对象的标记记录。
  4. 筛选回收:

算法:

小结

每种收集器都有自己的优点和不足,如此多的收集器只是为了在不同的场景下令JVM虚拟机有更好的表现。

上一篇下一篇

猜你喜欢

热点阅读