垃圾收集器

2018-12-27  本文已影响0人  平头哥2015

如果说垃圾收集算法是内存回收的方法论,垃圾收集器就是内存回收的具体实现。Java虚拟机规范中对垃圾收集器应该如何实现并没有任何规定,因此不同的厂商、不同版本的虚拟机所提供的垃圾收集器都可能会有很大的差别,并且一般都会提供参数供用户根据自己的应用特点和要求组合出各个年代所使用的收集器。这里讨论的收集器基于Sun HotSpot虚拟机1.6版Update 22,这个虚拟机包含的所有收集器如下图所示。


image.png

图中列出了7种作用于不同分代的收集器,如果两个收集器之间存在连线,就说明它们可以搭配使用。

Serial收集器

Serial收集器是最基本、历史最悠久的收集器,曾经(在JDK 1.3.1之前)是虚拟机新生代收集的唯一选择。

缺点

优点

简单而高效(与其他收集器的单线程比),对于限定单个CPU的环境来说,Serial收集器由于没有线程交互的开销,可以获得最高的单线程收集效率。

应用场景

到现在为止,它依然是虚拟机运行在Client模式下的默认新生代收集器。在用户的桌面应用场景中,分配给虚拟机管理的内存一般来说不会很大,收集几十兆甚至一两百兆的新生代,停顿时间完全可以控制在几十毫秒,最多一百多毫秒以内,只要不是频繁发生,这点停顿是可以接受的。所以Serial收集器对于运行在Client模式下的虚拟机来说是一个很好的选择。

JVM参数


ParNew收集器

ParNew收集器其实就是Serial收集器的多线程版本,除了使用多线程进行垃圾收集之外,其余行为包括Serial收集器可用的所有控制参数、收集算法、Stop The World、对象分配规则、回收策略等都与Serial收集器完全一样。实现上这两种收集器也共用了相当多的代码。

缺点

ParNew收集器在单CPU的环境中绝对不会有比Serial收集器更好的效果,甚至由于存在线程交互的开销,在通过超线程技术实现的两个CPU的环境中都不能百分之百地保证能超越Serial收集器。

优点

随着可以使用的CPU的数量的增加,ParNew收集器对于GC时系统资源的利用很有好处。ParNew收集器默认开启的收集线程数与CPU的数量相同,在CPU非常多的环境下(比如32个),可以使用-XX:ParallelGCThreads参数来限制垃圾收集的线程数。

应用场景

ParNew收集器除了多线程收集之外,其它与Serial收集器相比并没有太多创新之处,但它却是许多运行在Server模式下的虚拟机中首选的新生代收集器,其中有一个与性能无关但很重要的原因是,除了Serial收集器外,目前只有它能与CMS收集器配合工作。CMS作为老年代的收集器,无法与在JDK 1.4.0中已经存在的新生代收集器Parallel Scavenge配合工作(原因是Parallel Scavenge收集器及G1收集器都没有使用传统的GC收集器代码框架,而是另外独立实现。),所以在JDK 1.5中使用CMS来收集老年代的时候,新生代只能选择ParNew或Serial收集器中的一个。ParNew收集器也是使用-XX:+UseConcMarkSweepGC选项后的默认新生代收集器,也可以使用-XX:+UseParNewGC选项来强制指定它。

JVM参数


Parallel Scavenge收集器

Parallel Scavenge收集器跟ParNew收集器一样也是一个多线程的新生代收集器,也是使用复制算法。

特点

Parallel Scavenge收集器的特点是它的关注点与其它收集器不同,CMS等收集器的关注点是尽可能地缩短垃圾收集时用户线程的停顿时间,而Parallel Scavenge收集器的目标则是达到一个可控制的吞吐量(Throughput)。所以Parallel Scavenge收集器也经常被称为“吞吐量优先”收集器。

吞吐量

吞吐量是CPU用于运行用户代码的时间与CPU总消耗时间的比值,即吞吐量 = 运行用户代码的时间 / (运行用户代码的时间 + 垃圾收集时间)。Parallel Scavenge收集器提供了两个参数用于精确控制吞吐量,分别是控制最大垃圾收集停顿时间的-XX:MaxGCPauseMillis参数及直接设置吞吐量大小的-XX:GCTimeRatio参数。

应用场景

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

JVM参数


Serial Old收集器

Serial Old是Serial收集器的老年代版本,它同样是一个单线程收集器,使用“标记-整理”算法。

应用场景

Serial Old收集器主要也是用于Client模式下的虚拟机。如果在Server模式下,它主要有两大用途:
在JDK 1.5及之前的版本中与Parallel Scavenge收集器搭配使用。Parallel Scavenge收集器架构中本身有PS MarkSweep收集器来进行老年代收集,并没有直接使用Serial Old收集器,但是PS MarkSweep收集器是以Serial Old收集器为模板设计的,与Serial Old的实现非常接近。
作为CMS收集器的后备预案,在并发收集发生Concurrent Mode Failure的时候使用。


Parallel Old收集器

Parallel Old是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。

出现的原因

这个收集器是JDK 1.6中才开始提供的,在此之前,新生代的Parallel Scavenge收集器只能和Serial Old(PS MarkSweep)收集器配合工作。由于单线程的老年代Serial Old收集器在服务端应用性能上的“拖累”,即便使用了Parallel Scavenge收集器也未必能在整体应用上获得吞吐量最大化的效果,又因为老年代收集中无法充分利用服务器多CPU的处理能力,在老年代很大而且硬件比较高级的环境中,这种组合的吞吐量甚至还不一定有ParNew加CMS的组合“给力”。

应用场景

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

JVM参数


CMS(Concurrent Mark Sweep)收集器

CMS收集器是HotSpot在JDK 1.5中推出的第一款真正意义上的并发收集器,它第一次实现了让垃圾收集线程与用户线程(基本上)同时工作,是一种以获取最短回收停顿时间为目标的收集器。

工作原理

CMS收集器是基于“标记-清除”算法实现的,它的工作流程可以分为4个步骤:

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

优点

CMS是一款优秀的收集器,它的主要优点是并发收集、低停顿。Sun的一些官方文档里称它为并发低停顿收集器(Concurrent Low Pause Collector)。

缺点

主要有三个显著的缺点:

应用场景

CMS收集器非常适合B/S系统服务端这类重视服务响应速度,希望系统停顿时间最短,以给用户带来较好体验的应用。

JVM参数


G1(Garbage First)收集器

G1收集器是当前收集器技术发展的最前沿成果。

优点

G1收集器与CMS收集器相比有三个显著的改进:

工作原理

相对于其它收集器对整个新生代或老年代进行垃圾收集,G1收集器极力地避免全区域的垃圾收集。G1收集器将整个Java堆(包括新生代、老年代)划分为多个大小固定的独立区域(Region),并且跟踪这些区域里面的垃圾堆积程度,在后台维护一个优先列表,每次根据允许的收集时间,优先回收垃圾最多的区域(Garbage First名称的来由)。区域划分及有优先级的区域回收,保证了G1收集器在有限的时间内可以获得最高的收集效率。


其它的JVM参数

上一篇 下一篇

猜你喜欢

热点阅读