JVM-5. 垃圾回收器

HotSpot中包含的收集器如下图所示:


HotSpot的垃圾收集器

1. Serial/ Serial Old收集器

  • 最基本,历史最久
  • 新生代采取复制算法,暂停所有用户线程
  • 老年代采取标记-整理算法,暂停所有用户线程
  • 单线程,进行垃圾收集时必须暂停其他所有工作线程
  • 最简单,单线程里面最高效
  • Client模式下默认新生代收集器

2. PerNew收集器

  • Serial收集器的多线程版本
  • Server模式下首选的新生代收集器
  • 除Serial收集器外,只有它能与CMS收集器配合工作
  • -XX:+UseConcMarkSweepGC选项之后默认的新生代收集器
  • -XX:UsePerNewGC强制指定
  • -XX:ParallelGCThreads参数限制垃圾收集器的线程数。

3. Parallel Scavenger收集器

  • 使用复制算法的收集器
  • 并行多线程收集器
  • 目标是达到一个可控的吞吐量(Throughput)
  • 精确控制吞吐量的参数:
    • -XX:MaxGCPauseMillis ,接受一个大于0的毫秒数,收集器将尽可能保证内存回收花费的时间不超过设定值。注意:时间越小,收集越频繁
    • -XXGCTimeRatio参数,直接设置吞吐量,接受一个大于0小于100的整数,即垃圾收集时间占总时间的比率,也就是吞吐量的倒数,默认值99,即默认最大1%的垃圾回收时间。
  • -XX:+UseAdaptiveSizePolicy,开关参数,打开之后不需要手工指定新生代的大小(-Xmm),Eden与Survivor比例(-XXSurvivorRatio)、晋升老年代对象年龄(-XX:PretenureSizeThreshold)等细节参数,虚拟机根据当前系统运行情况收集性能监控信息,动态调整这些参数自适应调节(GC Ergonomics)最合适的停顿时间和最大吞吐量。

4. Serial Old收集器

  • Serial收集器的老年代版本
  • 单线程收集器
  • 使用“标记-整理”的办法
  • 在Client模式下作为虚拟机的默认老年代收集器
  • 在Server模式下可以和Parallel Scavenge收集器搭配
  • 在Server模式下作为CMS的后备,在并发时和Concurrent Mode Failure时使用

5. Parallel Old收集器

  • Parallel Scavenge收集器的老年代版本
  • 多线程处理
  • 使用“标记-整理”算法
  • 从JDK1.6开始提供
  • 在需要注意吞吐量和CPU资源敏感的时候优先考虑Parallel Scavenge+Parallel Old组合

6. CMS收集器

  • CMS = Concurrent Mark Sweep
  • 以获取最短回收停顿时间为目标
  • 适合在注意服务器响应速度,希望系统停顿时间最短,比如互联网网站或者B/S系统服务端。
  • 基于“标记-清除”
    • 初始标记(CMS initial mark)
      • 需要全暂停,但是仅仅标记GC Roots能关联到的对象,速度很快
    • 并发标记(CMS Concurrent mark)
      • 进行GC Roots Tracing的过程,和用户线程一起工作
    • 重新标记(CMS remark)
      • 全暂停
      • 为了修正并发标记期间用户线程导致的记录变化
      • 一般比初始标记长,远比并发标记时间短
    • 并发清除(CMS Concurrent sweep)
      • 和用户线程一起工作
  • 缺点在于:
    • 对于CPU资源和敏感,因在并发回收阶段会占用线程资源,会导致应用程序变慢,总吞吐量降低
      • 无法清除浮动垃圾(Floating Garbage)因为在垃圾回收阶段用户进程可能产生新的垃圾,但是出现在标记阶段之后,无法在当次处理,叫浮动垃圾。
      • CMS收集器需要预留空间提供并发收集时的程序运行,用-XX:CMSInitiatingOccupancyFraction设置触发收集的百分比,JDK1.5 默认68%,JDK1.6默认92%
      • CMS运行期间预留的内存无法满足程序需要,会临时启动Serial Old收集器重新进行老年代手机
  • 基于“标记-清楚”的算法会产生大量碎片
    • -XX:+UseCMSCompactAtFullCollection参数(默认开启),在FullGC时开启内存碎片的整合过程,解决空间碎片问题,但是停顿时间变长
    • -XX:CMSFullGCsBeforeCompaction:设置执行多少次不压缩的Full GC,再进行带压缩的(默认为0,标识每次Full GC时都需要进行碎片整理)

7. G1收集器

  • Garbage-First
  • 面向服务端应用
  • 并行与并发利用多个CPU来缩短Stop-The-World时间
  • 分代收集
  • 空间整合,从整体上基于“标记-整理”,聚不上基于“复制”,不会产生碎片
  • 可预测的停顿
  • 保留新生代和老年代的概念,但是它们之间不再物理隔离,都是一部分Region的集合。
  • 跟踪Region垃圾堆价值大小,后台维护优先列表,每次根据允许的收集时间,回收价值最大的Region。
  • 通过Remembered Set来避免全堆扫描,每个Region都有一个对应的Remembered Set。在Reference对象被写入时,中断写操作,检查Reference引用的对象是否处于不同的Region,如果是,通过CardTable把相关引用的信息记录到被引用对象所属的Region的Remembered Set中。
  • 除了维护Remembered Set的操作,G1收集器运作包括以下几个步骤:
    • 初始标记(Initial Marking):记录GC Roots能关联到的对象。时间短,中断用户操作。
    • 并发标记(Concurrent Marking),从GC Roots开始进行可达性分析,耗时较长,可并行
    • 最终标记(Final Marking),把并发标记期间对象变化记录在线程Remembered Set Logs中,并把其中的数据合并到Remembered Set中。需要停顿线程,但是可并行执行。
    • 筛选回收(Live Data Counting Evacuation)对各个Region的回收价值和成本进行排序,根据用户期望的GC停顿时间来指定回收计划。

8. GC日志

一般包括:

  • GC发生时间,一般用Java虚拟机启动经过的秒数
  • GC和“Full GC”,标识垃圾收集停顿类型,是否发生Stop-The-World
  • GC发生区域
  • GC钱内存区域使用容量->GC后内存区区域使用容量(内存区域总容量)
  • GC占用时间

9. 垃圾收集器参数

参数 描述
UseSerialGC 虚拟机在Client模式下的默认值,使用Serial+Serial Old收集器组合进行内存回收
UseParNewGC 打开后,使用ParNew+Serial Old的收集器组合进行内存回收
UseConcMarkSweepGC 打开后,使用ParNew + CMS + Serial Old的组合进行回收,其中Serial Old作为CMS收集器出现Concurrent Mode Failure失败后的后备收集器使用
UseParallelGC 在Server模式下的默认值,打开后使用Parallel Scavenge+Serial Old(PS MarkSweep)收集器组合进行回收
UseParallelOldGC 打开后,使用Parallel Scavenge + Parallel Old组合进行内存回收
SurvivorRatio 新生代中Eden区域和Survivor区域的容量比值,默认是8,也就是Eden:Survivor = 8:1
PretenureSizeThreshold 直接晋升到老年代的对象大小,设置这个参数之后,大于这个参数的对象将直接在老年代分配。
MaxTenuringThreshold 晋升到老年代的对象年龄,这个对象在坚持过一次Minor GC之后,年龄就增加1,当超过这个参数后进入老年代。
UseAdaptiveSizePolicy 动态调整Java堆中各个区域的大小以及进入老年代的年龄
HandlePromotionFailure 是否允许分配担保失败,即老年代的剩余空间不足以应付新生代的整个Eden和Survivor区的所有对象都存活的极端情况
ParallelGCThreads 设置并行GC时进行内存回收的线程数
GCTimeRatio GC时间占总时间的比例,默认为99%,即允许1%的GC时间,仅在使用Parallel Scavenge收集器时有效
MaxGCPauseMillis 设置GC最大停顿时间,尽在使用Parallel Scavenge收集器时生效
CMSInitiatingOccupancyFraction 设置CMS在老年代空间被使用多少之后触发垃圾收集,默认为68%。仅在CMS收集器时生效
UseCMSCompactAtFullConllection 设置CMS收集器在完成垃圾收集后是否要进行一次内存整理,仅在CMS收集器时生效
CMSFullGCsBeforeCompaction 设置CMS收集器在进行若干次垃圾回收后再启动一次内存碎片整理,仅在CMS收集器时生效

你可能感兴趣的:(JVM-5. 垃圾回收器)