HotSpot虚拟机的垃圾收集器:
Serial收集器
是一个单线程的收集器,在它进行垃圾收集时,必须暂停其他所有的工作线程,直到它收集结束。
ParNew收集器
是Serial收集器的多线程版本,目前只能与CMS收集器配合工作。
Parallel Scavenge 收集器
Parallel Scavenge收集器称为“吞吐量优先”收集器。
Parallel Scavenge收集器的目标是达到一个可控制的吞吐量。所谓吞吐量就是CPU用于运行用户代码的时间与CPU总消耗时间的比值。
即吞吐量 = 运行用户代码时间 / (运行用户代码时间 + 垃圾收集时间)
主要适合在后台运算而不需要太多交互的任务。
Serial Old收集器
是一个单线程收集器,使用“标记-整理”算法,可作为CMS收集器的后备方案,在并发收集器发生Concurrent Mode Failure时使用。
Parallel Old收集器
Parallel Old 是Parallel Scavenge收集器的老年代版本,使用多线程和“标记-整理”算法。
CMS收集器
CMS(Concurrent Mark Sweep)收集器是一种以获取最短回收停顿时间为目的的收集器。
由于整个过程中耗时最长的并发标记和并发清除过程收集器线程都可以与用户线程一起工作,所以,从整体上来说,CMS收集器的内存回收过程与用户线程一起并发执行的。
CMS的明显缺点:
一、CMS收集器无法处理浮动垃圾(Floating Garbage),可能出现“Concurrent Mode Failure”失败而导致另一次Full GC的产生。
由于CMS并发清理阶段用户线程还在运行着,伴随程序运行自然就还会有新的垃圾不断产生,这一部分垃圾出现在标记过程之后,CMS无法在当次收集中处理掉它们,只好留待下一次GC时再清理掉。这一部分垃圾就成为“浮动垃圾”。也是由于在垃圾收集阶段用户线程还需要运行,那也就还需要预留有足够的内存空间给用户线程使用,因此CMS收集器不能像其他收集器那样等到老年代几乎完全被填满了再进行收集,需要预留一部分空间提供并发收集时的程序运作使用。
要是CMS运行期间预留的内存无法满足程序的需要,就会出现一次“Concurrent Mode Failure”失败,这时虚拟机将启动后备方案:临时启用Serial Old收集器来重新进行老年代的垃圾收集,这样停顿时间就很长了。
二、CMS是一款基于“标记-清除”算法实现的收集器,这意味着收集结束时会有大量空间碎片产生。
空间碎片过多时,将会给大对象分配带来很大麻烦,往往会出现老年代还有很大空间剩余,但是无法找到足够大的连续空间来分配当前对象,不得不提前触发一次Full GC。
为了解决这个问题,CMS收集器提供了一个-XX:+UseCMSCompactAtFullCollection开关参数(默认是开启的),用于在CMS收集器顶不住要进行FullGC时开启内存碎片的合并整理过程,内存整理的过程是无法并发的,空间碎片问题没有了,但停顿时间不得不变长。
虚拟机设计者还提供了另外一个参数:-XX:CMSFullGCsBeforeCompaction,这个参数是用于设置执行多少次不压缩的Full GC后,跟着来一次带压缩的(默认值为0,表示每次进入Full GC时都进行碎片整理)。
查看JDK默认使用的垃圾收集器,执行命令:java -XX:+PrintCommandLineFlags -version
引用《深入理解Java虚拟机:JVM高级特性与最佳实践》的介绍:
所以,jdk8环境下,默认使用 Parallel Scavenge(新生代)+ Serial Old(老年代)
-XX:+PrintCommandLineFlagsjvm参数可查看默认设置收集器类型
-XX:+PrintGCDetails亦可通过打印的GC日志的新生代、老年代名称判断