【Java】JVM垃圾收集器

概述

垃圾收集算法是垃圾回收的方法论, 垃圾回收器则是垃圾回收的具体实现。

各个厂商差异较大, 这里只讨论常用的HotSpot虚拟机。

在这里插入图片描述

HotSpot垃圾收集器可搭配使用的关系图。

为了应对不同的场景和需求,需要选择不同的新生代和年老代垃圾收集器搭配使用。

Serial

串行收集器,采用复制算法, HotSpot运行在Client模式下的默认新生代收集器。

特点:

  • 单线程, 一但进行垃圾收集必须暂停其他所有线程(Stop The World)

  • 单线程垃圾收集简单高效。

参数 :

-XX:+UseSerialGC  使用Serial作为新生代收集器

在这里插入图片描述

ParNew

并行收集器, 采用复制算法, Serial的多线程版本, Server模式下的首选新生代收集器

特点:

  • 多线程, 多核CPU下对系统资源的利用率较高, 其余属性与Serial相同.

  • 除了Serial外唯一能和CMS收集器配合工作的收集器.

参数:

-XX:+UseParNewGC        指定使用ParNew垃圾收集器
-XX:ParallelGCThreads   指定垃圾收集的线程数

在这里插入图片描述

Parallel Scavenge

并行多线程新生代收集器, 采用复制算法.

特点:

  • 关注垃圾收集器的吞吐量,
  • 实现吞吐量可控, 高效地利用CPU资源.
  • 无法与CMS收集器配合工作

参数:

-XX: MaxGCPauseMillis      收集器尽力保证收集时间不超过设定值.
-XX: GCTimeRatio   		    值是一个大于0小于100的整数, 即垃圾收集时间占总时间的比例.
-XX:+UseAdaptiveSizePolicy  开关参数,自动调整定-Xmn、 -XX:SurvivorRatio、-XX:PretenureSizeThreshold等
							参数以提供最合适的停顿时间和吞吐量.GC自适应调节.
-XX:+UseParallelGC          新生代使用Parallel收集器
 -XX:+UseParallelOldGC      老年代使用Parallel old收集器

Serial Old

Serial的老年代版本, 单线程收集器, 采用标记-整理算法, 在Client模式下使用.

特性:

  • 在JDK1.5以及之前的版本中与Parallel Scavenge配合使用
  • 可以作为CMS的后备预案, 在并发收集发生Concurrent Mode Failure时使用.

在这里插入图片描述

Parallel Old

Parallel Scavenge的年老代版本, 多线程上映标记-整理算法, jdk1.6中开始提供.

特性:

  • Parallel Scavenge+Serial Old地位尴尬. Parallel Scavenge + Parallel Old可以再之中吞吐量和CPU资源敏感的场合搭配使用.

在这里插入图片描述

CMS(Concurrent Mark Sweep)

目前主流的互联网企业选用的垃圾收集器. 使用标记-清除算法的年老代并发收集器

特性:

  • 低停顿
  • 无法处理浮动垃圾
  • 标记-清理算法造成碎片

收集过程:

  • 初始标记
    需要暂停其他线程, 标记一下GC Roots能够直接关联到的对象, 速度很快.
  • 并发标记
    并发执行, 进行GC Roots Tracing可达性分析, 对非直接关联对象进行标记, 耗时长
  • 重新标记
    暂停其他线程, 并发修正并发标记产生变动的对象的记录.
  • 并发清理
    并发运行, 清理标记的对象.

整个过程耗时最长的并发标记和并发清理都是并发执行的, 因此可以认为CMS是与用户线程并发执行的.

在这里插入图片描述

特点:

  • CMS启动回收线程数=(CPU数目 + 3) /4 对CPU资源敏感.
  • 无法处理浮动垃圾, 即在并发清理阶段产生的垃圾无法清除, 需要等到下一次GC. 需要留给用户线程内存空间, 预留的内存不够产生Concurrent Mode Failure 导致Full GC, JVM启动后备预案,临时启用Serial Old进行老年代垃圾收集.
    -XX:CMSInitiatingOccupancyFraction 剩余空间触发垃圾收集的百分比.
  • 标记-清理法产生大量碎片 -XX: CMSFullGCsBeforeCompaction 设置执行多少次不带压缩的Full GC后,运行一次带压缩的GC

G1收集器

款面向服务端应用的收集器,主要目标用于配备多颗 CPU 的服务器治理大内存.

整个Java堆划分成为多个大小相等的区域Region, 新生代和年老代是一部分Region的集合.

根据每个Region里面垃圾堆积的价值大小, 维护一个优先列表, 每次根据列表回收价值最大的Region, 保证了回收的效率.

建立Remembered Set 避免不同Region和区域间的对象引用. 每个Region都有一个Remembered Set, 当对引用进行操作时会维护被引用对象所属的Region的Remembered Set.

特点:

  • 并行与并发: 充分利用多CPU多核环境, 缩短Stop the World的时间.
  • 分代收集: 能够采用不同的方式去处理新创建的对象和已经存活了一段时间的多谢和熬过了多次GC的多谢.
  • 空间整合: 整体来看是给予标记-整理算法, 局部Region来看是基于复制算法. 因此运行期间不会产生碎片.
  • 可以预测的停顿. 低停顿是G1和CMS共同的关注点, G1还能建立可预测的停顿时间模型, 能够制定一个长度的时间片, 是垃圾收集不超过该时间.

收集过程:

  • 初始标记
    需要暂停其他线程, 标记一下GC Roots能够直接关联到的对象, 速度很快.
  • 并发标记
    并发执行, 进行GC Roots Tracing可达性分析, 对非直接关联对象进行标记, 耗时长
  • 最终标记
    需要暂停其他线程, 修正并发标记阶段因用户线程继续运行而导致标记发生变化的那部分对象的标记记录。
  • 筛选回收
    对每个Region的回收价值和成本进行排序, 根据用户期望的GC停顿时间进行回收.

参考:《深入理解Java虚拟机》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章