引言
前面,我们简单的了解了垃圾收集器的分类和几种组合,在我们开始后面的讨论前,要说下jvm的两种运行模式,一种client模式,另一种是server模式,默认情况下,我们使用的是client模式,我们可以使用-server命令强制开启server模式,两者最大的差别是,在server模式下jvm做了很多优化。现在让我们深入了解下各种垃圾收集器的运行场景和它们的特点。
各种收集器特点
Serial Garbage Collector
特点:采用单线程方式回收内存,单线程也意味着复杂度更低,占用内存更少,同时也意味着不能有效的利用多核的优势。
适用场景:串行收集器比较适合堆内存不高,单核甚至多核CPU的场景。
开启参数:-XX:+UseSerialGC(client模式默认值)
Serial Old Garbage Collector
特点:该收集器是针对老年代区域回收,采用标记-整理算法,其它与Serial Garbage Collector收集器特点一样,这里就不多讲了。
ParNew Garbage Collector
特点:该收集属于并行收集器,以关注吞吐量为目标的垃圾收集器,也是server模式下虚拟机中新生代的首选收集器。
适用场景:在中大型的堆上,且系统处理器至少多于一个。
开启参数:-XX:+UseParNewGC
Parallel Scavenge Garbage Collector
特点:该收集器与ParNew Garbage Collector收集器特点几乎一样,与ParNew最大的区别就是可设置的参数不一样,该收集器可以更加精准的控制GC停顿时间及吞吐量。Parallel Scavenge收集器还提供了一个参数-XX:+UseAdaptiveSizePolicy,打开参数后,就不需要手工指定新生代的大小(-Xmn)、Eden和Survivor区的比例(-XX:SurvivorRatio)、晋升老年代对象年龄(-XX:PretenureSizeThreshold)等细节参数了,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大的吞吐量,这种方式称为GC自适应的调节策略(GC Ergonomics)。
Parallel Old Garbage Collector
特点:它是除了serial old以外唯一一个可以与parallel scavenge搭配工作的年老代搜集器,为了避免serial old影响parallel scavenge可控制吞吐量的名声,parallel old就作为了parallel scavenge真正意义上的搭档。
开启参数:使用参数-XX:-UseParallelOldGC开启,不过在JDK6以后,它也是在开启parallel scavenge之后默认的年老代搜集器。
Concurrent Mark Sweep Garbage Collector
特点:是唯一一个在年老代采用标记/清除算法的搜集器,非常适合堆内存大,CPU核数多的服务端应用,并发收集、低停顿。
缺点:对CPU资源非常敏感,无法处理浮动垃圾,标记-清除算法会导致的空间碎片。
Garbage-First
特点:并行与并发(能充分利用多CPU、多核环境下的硬件优势)、分代收集、空间整合(不会产生内存空间碎片)、可预测的停顿(可以明确指定在一个长度为M毫秒的时间片段内,消耗在GC上的时间不得超过N毫秒)、横跨整个堆内存、避免全堆扫描。
总结
下面我们以一张图来总结下他们各自的特点:收集器 | 串行、并行or并发 | 新生代/老年代 | 算法 | 目标 | 适用场景 |
---|---|---|---|---|---|
Serial | 串行 | 新生代 | 复制算法 | 响应速度优先 | 单CPU环境下的Client模式 |
Serial Old | 串行 | 老年代 | 标记-整理 | 响应速度优先 | 单CPU环境下的Client模式、CMS的后备预案 |
ParNew | 并行 | 新生代 | 复制算法 | 响应速度优先 | 多CPU环境时在Server模式下与CMS配合 |
Parallel Scavenge | 并行 | 新生代 | 复制算法 | 吞吐量优先 | 在后台运算而不需要太多交互的任务 |
Parallel Old | 并行 | 老年代 | 标记-整理 | 吞吐量优先 | 在后台运算而不需要太多交互的任务 |
CMS | 并发 | 老年代 | 标记-清除 | 响应速度优先 | 集中在互联网站或B/S系统服务端上的Java应用 |
G1 | 并发 | both | 标记-整理+复制算法 | 响应速度优先 | 面向服务端应用,将来替换CMS |