HotSpot垃圾收集器

本篇主要介绍一下JVM的几种垃圾收集器。其示意图如下所示,上面的三个是新生代的收集器,下面三个是老年代的收集器,其中G1收集器是可以用于新生代和老年代的收集工作。

Serial(串行收集器)

用于新生代GC,复制算法,启动时默认为Client模式,GC的线程为单线程。缺点是因为单线程GC,会造成中断的时间(Sop-the-world)比较大。(对于单核的CPU来说,比并行收集的效率要高)其示意图如下所示:

ParNew(并行收集器)

与Serial类似,不同点在于它一般用于新生代的并行回收,而且通常情况下运行在Server模式(单核CPU下,性能可能比Serial还要差)。示意图如下所示:

Parallel Scavenge(并行回收)

用于新生代回收,复制算法,并行收集。与ParNew的不同是它的关注点不同,它可以精确的控制吞吐量。【吞吐量= 程序运行时间/(程序运行时间 + 垃圾收集时间),例如:JVM共运行了100min。其中垃圾收集花掉1min,那吞吐量就是99%】示意图如下所示:

Serial Old(串行收集器)

Serial收集器的老年代版本,使用标记-压缩(标记-整理)收集算法,主要用于启动模式为Client的JVM。示意图可以参考Serial串行收集器。

Parallel Old(并行收集器)

Parallel的老年代版本,使用标记-压缩(标记-整理)收集算法。其示意图可以参考Parallel并行收集。

CMS(concurrent mark sweep)

并发收集器(发生GC时,GC线程与应用线程同时运行)。是一种以最短响应为目标的收集器,适用于B/S架构的运行环境。使用标记-清除算法,因此会产生大量的内存碎片。CMS的收集步骤如下所示:

CMS收集器有以下3个明显的缺点:

对CPU资源非常敏感:其默认的回收线程数=(CPU数量+3)/ 4,也就是当4个CPU以上时,GC会占用不少于25%的CPU资源。当CPU数量较少时,GC占用的CPU资源就比较高。

无法处理浮动垃圾:在并发清理阶段,有用户线程运行,此时又会有新的垃圾产生。因此这部分垃圾只能在下一次GC时才能清除。CMS不能像其他收集器那样,等到老年代快满了才触发GC,它需要留出更多的空间。当然,可以通过-XX:CMSInitiatingOccupancyFraction的值来提高百分比,但是当内存不足时,很容易会出现“Concurrent Mode Failure”。此时JVM会临时启用Serial Old收集器,这样以来就会造成更大程度的停顿。

容易造成大量的内存碎片:CMS是基于“标记-清除”算法实现的,当GC结束时会产生大量的内存碎片。

GC参数总结

GC参数组合

​​​​


参考:《实战Java虚拟机》