如果说收集算法(标记-清除,复制,标记-整理、分代收集算法)是内存回收的方法论,那么垃圾收集器就是内存回收的具体实现。目前HotSpot虚拟机所包含的所有收集器如下图。
上面7种作用不同分代的收集器,如果两个收集器之间存在连线,就说明他们可以搭配使用。虚拟机所处的区域,则表示它是属于新生代收集器还是老年代收集器。HotSpot实现如此多的垃圾收集器,就是因为目前没有完美的收集器出现,只能选择对应最合适的收集器。
一、理解相关概念
1.并行(Parallel)
并行指的是多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态。
2.并发(Concurrent)
并行指的是用户线程与垃圾收集线程同时执行(但不一定是并行,可能会交替执行),用户程序在继续运行,而垃圾收集程序运行在另一个CPU上。
3.吞吐量(Throughput)
吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值,即吞吐量=运行用户代码时间/(运行用户代码时间+ 垃圾收集时间)。
二、新生代收集器
1.Serial收集器
Serial收集器是最基本、发展历史最悠久的收集器,它是采用复制算法的新生代收集器。顾名思义Serial(串行)收集器是一个单线程收集器。它只会使用一个CPU或者一条收集线程去完成收集工作,在进行垃圾收集时,必须暂停其他所有工作线程,直到它收集结束。("Stop The World")。曾经在JDK1.3.1之前是新生代收集的唯一选择。
实际上Serial收集器并非是“老而无用,食之无味弃之可惜”的鸡肋,到目前为止,它依然是虚拟机运行在Client模式下默认的新生代收集器。它有着优于其他收集器的地方:简单而高效(与其他收集器的单线程相比),对于限定单个CPU的环境来说,Serial收集器由于没有线程交互的开销,专心做垃圾收集自然可以获得更高的单线程收集效率。
2.ParNew收集器
ParNew收集器是Serial收集器的多线程版本,也是新生代收集器。除了使用多线程进行垃圾收集之外,其余行为包括Serial收集器可用的所有控制参数(例如:-XX:SurvivorRatio、-XX:PretenureSizeThreshold、-XX:HandlePromotionFailure等)、收集算法、Stop The World、对象分配规则、回收策略等都与Serial收集器完全一样,在是线上,这两种收集器也共用了相当多代码。
ParNew收集器除了多线程收集之外,其他与Serial收集器相比并没有太多创新之处。但它却是许多运行在Server模式下的虚拟机首选的新生代收集器。除了Serial收集器之外,目前只有它能和CMS收集器(Concurrent Mark Sweep)配合工作,CMS收集器是JDK1.5推出的具有划时代意义的收集器。它实现了让垃圾收集线程和用户线程(基本上)同时工作。
ParNew收集器在单CPU环境下绝对不会比Serial收集器更过更好,甚至由于存在线程交互的开销,该收集器在通过超线程技术实现的两个CPU环境都不能百分百超越Serial收集器。在多CPU环境下,它对GC系统资源的有效利用是很有好处的。它默认开启的收集线程与CPU数量相同,在CPU非常多的情况下使用-XX:ParallerGCThreads参数进行设置。
3.Parallel Scavenge收集器
Parallel Scavenge收集器也是一个并行收集器,它也是使用复制算法的收集器。Parallel Scavenge收集器的目标是达到一个可控制的吞吐量(Throughput)。吞吐量高则可以高效地利用CPU时间,尽快完成程序的运算任务,主要适合在后台运算而不需要太多交互的任务。
Parallel Scavenge收集器提供两个参数用于精准控制吞吐量,分别是最大垃圾停顿时间-XX:MaxGCPauseMillis参数和直接设置屯吞吐量大小的-XX:GCTimeRatio参数。
- MaxGCPauseMillis参数允许的值是一个大于0的毫秒数,收集器能尽可能保证内存回收花费的时间不超过该值。
- GCTimeRatio参数的值应当是一个大于0且小于100的整数,也就是