深入理解JVM(四)——各个版本提供的垃圾收集器

上一篇将的回收算法是内存回收的方法论,本篇讲垃圾收集器的具体实现,Java虚拟机规范并没有对齐做出规定和限制,所以不同厂商,不同版本的虚拟机,垃圾收集器有很大的区别。

收集器名称 区域 说明
Serial 新生代 单线程,GC时必须停止其它线程直到收集结束;JVM运行在client模式下新生代的默认收集器,简单有效;采用复制算法
ParNew 新生代 Serial收集的多线程版,保留Serial的参数控制,算法等,暂停所有用户线程,采用复制算法;JVM运行在server的首先的新生代收集器;只有它能和CMS配合工作
Parallel Scavenge 新生代 采用复制算法,并行的多线程收集器,与ParNew不同的是,关注点不是停顿时间,而是可控制的吞吐量,即运行用户代码的时间/(运行用户代码的时间+垃圾收集的时间)。可设置最大GC时间和吞吐量大小等参数,也可以让JVM自适应调整策略
G1 新生代/老年代 收集器最前沿版本,JDK 1.7,代替CMS的新产品
CMS 新生代 concurrent Mark Sweep,已获取最短回收停顿为目标,大部分的互联网站及服务端采用的方式,标记-清除算法
Serial Old(MSC) 老年代 Serial的老年版,单线程收集器,采用标记-整理算法,主要是client模式的JVM使用
Parallel Old 老年代 Parallel Scavenge的老年版,多线程,标记整理算法

并行(Parallel):指多条垃圾收集线程并行工作,但此时用户线程仍然处于等待状态
并发(Concurrent):指用户线程和垃圾收集线程同时执行(但不一定是并行的,可能是交替执行),用户程序继续运行,而垃圾收集程序运行在另外的CPU上。

CMS

  1. 初始标记(stop the world)
    单线程,仅仅关联GC Roots能直接关联到的对象,速度很快
  2. 并发标记
    多线程,和用户线程并发, 进行GC Roots Trancing的过程
  3. 重新标记 (stop the world)
    多线程,为了修正并发标记期间因用户程序继续运行而导致的标记产生变动的那一部分对象,比初始标记略长,但远比并发标记短
  4. 并发清除
    多线程,和用户线程并发

3个明显的缺点
1. CMS收集器对CPU资源非常敏感,当然面向并发的设计都对资源敏感,会占用一部分的线程,影响应用程序,默认启动(CPU数量+3)/4个回收线程。
2. CMS收集器无法处理浮动垃圾。并发清理过程中,用户线程还在运行,伴随运行就会有新的垃圾产生,这部分出现在标记之后,CMS无法清除,只能等待下一次GC。CMS为了满足并发的需求,需要预留内存空间。
3. 标记-清理算法导致老年代空间碎片化,CMS提供参数解决,在Full GC前,开启内存碎片的合并整理过程。

G1

G1收集器的运作

  1. 初始标记
    单线程,仅仅关联GC Roots能直接关联到的对象,速度很快;修改TAMS(Next Top at Mark Start),为了下一阶段用户程序并发运行,能在正确可用的Region上创建对象
  2. 并发标记
    同CMS,并且虚拟机记录将并发标记时间对象变化记录在线程Remembered Set Logs中
  3. 最终标记
    同CMS,将Remembered Set Logs里面的数据合并到Remembered Set中
  4. 筛选回收
    标记-整理算法,Region

G1具备一下特点
1. 并行与并发,充分利用多CPU和多核的硬件条件,缩短stop the world的时间,可以通过并发的方式让Java程序继续执行
2. 分代收集,不需要与其它收集器配合,独立管理GC堆,采用不同的方式管理不同GC年龄的对象
3. 空间整合,与CMS不同,采用的是标记-整理算法,从局部上看是通过复制算法实现的
4. 可预测的停顿, G1追求低停顿外,还建立了可预测的停顿时间模型,能让使用者明确在一个长度为M毫秒的时间片断内,消耗在垃圾收集上的时间不超过N毫秒

垃圾收集器的组成

不同的垃圾收集器可以互相搭配使用,虽然我们对垃圾收集器进行比较,但是目前为止还没有最好的垃圾收集器出现,更加没有万能的垃圾搜集器。以下未列举的即为不可组合使用。

以下时各种垃圾收集器的搭配使用

新生代 老年代 说明
Serial Serial Old(MSC) 新生代采用复制算法,暂停所有用户线程,单线程;老年代采用标记-整理算法,暂停所有用户线程,单线程
Serial CMS 新生代采用复制算法,暂停所有用户线程,单线程;老年代,采用CMS收集器,初始标记(单线程,stopTheWorld),重新标记(并发标记),重新标记(多线程,stopTheWorld),并行清除(并行清理,标记-清理算法)
ParNew Serial Old(MSC) 新生代采用复制算法,stopTheWorld,多线程;老年代MSC同上
ParNew CMS 新生代同上ParNew,老年代同上CMS
Parallel Scavenge Serial Old(MSC) Parallel Scavenge收集方式和ParNew一致,重点关注吞吐量,但被MSC限制
Parallel Scavenge Parallel Old 老年代,多线程,标记-整理算法,吞吐量优先组合
G1 G1 Java堆的内存布局有很大的不同,划分成多个大小相等的独立区域Region,新生代和老年代不在物理隔离,能有效避免整个Java堆全区域的GC

你可能感兴趣的:(Java,JVM)