JVM 经典垃圾收集器大合集

经典垃圾收集器大合集

收集算法可以看成是内存回收的方法论,垃圾收集就是它的实际落地。

JVM规范中对垃圾收集器应该如何实现并没有任何规定,所以不同的版本的虚拟机包含的垃圾收集器可能会有很大差别。

Serial收集器:

特点:

  • 收集器中的老大哥(最基础,历史最悠久,JDK1.3.1之前的唯一选择),
  • 一个单线程就是干,最稳定而且效率高
  • Stop the world:回收的时候,其他所有线程必须暂停
  • HotSpot Client模式下默认的新生代收集器
  • -XX:+UseSerialGC 使用Serial(年轻代)+Serial Old(老年代)组合

ParNew收集器

特点:

  • Serial的多线程版本
  • 除了Serial收集器外,只有ParNew 可以与CMS收集器配合
  • 就是说CMS被激活后(-XX:+UseConcMarkSweepGC),ParNew是默认的新生代收集器,也可以使用-XX:UseParNewGC来强制指定或者禁止。
  • ParNew在单核心CPU的环境下是无法拥有比Serial收集器更好的效果
  • -XX:ParallelGCThreads参数来限制垃圾收集的线程数

Parallel Scavenge收集器

特点:

也是一款新生代收集器,并行多线程标记-复制算法

关注系统的吞吐量Throughput,就是处理器用于运行用户代码的时间与处理器总耗时的比值。

公式:

 

吞吐量越高,表示可以最高效率的利用处理器资源,适合后台运算而不需要太多交互的分析任务。当然这都是理论上的。

 

-XX:MaxGCPauseMillis最大垃圾收集停顿时间 范围是大于0的毫秒数,收集器会尽力保证内存回收花费时间不超过用户设定的值。但是并不是这个值越小就使得系统的垃圾收集速度加快,因为停顿时间是以吞吐量和新生代空间为代价的

-XX:GCTimeRatio=nnn 关注吞吐量 范围0~100,就是垃圾收集时间不会超过占总时间的 1/(1+nnn)。

-XX:+UseAdaptiveSizePolicy 开启GC自适应调节策略Ergonomics,系统会自动设置新生代-Xmn大小、Eden、Survivor区比例-XX:SurvivorRatio、

晋升老年代对象大小-XX:PretenureSizeThreshold)等细节参数

Serial Old收集器

是Serial的老年代版本,也是单线程收集器标记-整理算法。

Parallel Old收集器

特点:

  • Parallel Scavenger的老年代版本,支持多线程并发,标记整理算法。
  • JDK1.6后才有
  • 与Parallel Scavenger可以搭配使用

CMS收集器

特点:

Concurrent Mark Sweep是以获取最短回收停顿时间为目标的收集器,支持并发,标记-清除,停顿时间短,可以给用户更好的交互体验。

4个步骤 初始标记,并发标记,重新标记,并发清除

适用组合:ParNew+CMS

缺点:

  • 处理器资源非常敏感。因为并发处理需要占用线程,CMS默认回收线程是(CPU核心+3)/4,但是当处理器核心不够4个时,CMS就会对用户程序的影响会变大。所以后来又出现了iCMS变种,但是事实证明没啥特别好的效果。以至于在JDK9后i-CMS就被完全废弃了。
  • CMS无法处理‘浮动垃圾’Floating Garbage,有可能出现‘Concurrent Mode Failure’而触发另一次“Stop the World”的Full GC产生。浮动垃圾就是标记过程中产生的新垃圾对象,CMS无法在当次处理,只能安排在下一次进行收集清理。-XX:CMSInitiatingOccupancyFraction设置CMS回收老年代使用空间的占比但是这个值不能太高,会有导致大量的并发失败风险,从而导致性能降低,具体要根据实际的情况来配置
  • CMS是标记清除的算法实现,会产生大量空间碎片可以通过-XX:+UseCMSCompactAtFullCollection 在FullGC时做一次整理[JDK9开始废弃]。-XX:CMSFullGCsBeforeCompaction 要求在执行过若干次不整理空间的FullGC后,下一次进入FullGC会先进行整理 默认0,表示每次进入FullGC都会整理 [JDK9开始废弃]

Garbage First收集器

特点:

简称G1收集器,简单来说就是比较厉害,被大家认为是收集器发展的一个里程碑成果,开创了收集器面向局部收集的设计思路和基于Region的内存布局形式。(说明不是浪得虚名的)

主要面向服务端应用的垃圾收集器,JDK9之后被认为是CMS的替代品

JDK9之后的HotSpot如果开启-XX:+UseConcMarkSweepGC,会收到CMS未来会被废弃的警告。

一般来说收集器都是针对整个新生代或者老年代,要么就是整个堆,但是G1可以面向堆的任何部分进行回收,标准不是属于哪个分代,而是哪块内存垃圾多,回收收益大,这就是Mixed GC模式。

G1虽然也有新生代,老年代的概念,但是已经不再是固定的。而是一系列区域的动态集合。-XX:MaxGCPauseMillis用户可以设定允许的收集停顿时间,默认200ms,如果设置太低,会导致时间短,无法回收足够的内存,最终引发FullGC

从整体来看G1是基于 标记整理 算法的收集器,所以和CMS相比不会产生空间碎片。

小结:

不同收集器是跟随JVM的发展而出现的,

不管是新生代,老年代,不管是单线程,多线程,实际使用中要考虑不同的平台(服务端,客户端),不同的需求(吞吐量,低停顿),不同的系统资源(处理器核数,线程数),不同的虚拟机版本(JDK6,7,8,9,……)来决定使用哪种收集器配合。

虚拟机的参数要由实际运行的用户程序来决定使用哪些参数

https://blogs.oracle.com/jonthecollector/our-collectors

原文地址:https://www.cnblogs.com/dreamtaker/p/13357463.html