JVM - 垃圾回收器概述

既然选择了远方,即便天寒地冻,路遥马亡,我本就一无全部,又有何惧。算法

串行收集器

  1. 单线程、独占式进行垃圾回收
  2. 独占式:应用程序线程会中止工做,只有垃圾回收线程在工做,即 stop the world。
  3. 在并行能力较差的机器上,会有更好的性能表现。

新生代串行收集器

  1. 新生代串行收集器使用的是 复制算法
  2. 使用 -XX:UseSerialGC, -XX:+UseConcMarkSweepGC -XX:-UseParNew 启用
  3. GC 日志以下所示
[GC (Allocation Failure) [DefNew: 67932K->0K(78720K), 0.0002327 secs] 68792K->859K(253504K), 0.0002491 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
复制代码

老年代串行收集器

  1. 老年代串行收集器使用的是 标记-压缩算法
  2. 使用 -XX:UseSerialGC、-XX:+UseParNewGC 启用
  3. GC 日志以下
[Full GC (Allocation Failure) [Tenured: 10250K->10249K(15360K), 0.0187416 secs] 10250K->10249K(19968K), [Metaspace: 9228K->9228K(1058816K)], 0.0187608 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]复制代码

并行收集器

ParNew

  1. 新生代垃圾回收器
  2. 新生代串行收集器的多线程版本
  3. 与新生代串行收集器的区别仅在于垃圾回收时,是多线程并行。
  4. 使用 -XX:UseParNew、-XX:UseConcMarkSweepGC 启用
  5. GC 日志以下
[GC (Allocation Failure) [ParNew: 82K->24K(4608K), 0.0003178 secs][Tenured: 15353K->10251K(15360K), 0.0185459 secs] 15435K->10251K(19968K), [Metaspace: 8855K->8855K(1056768K)], 0.0188925 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 
复制代码

ParallelGC

  1. 新生代垃圾回收器,使用 复制算法
  2. 与 ParNew 相比,ParallelGC 更关注吞吐量
  3. -XX:MaxGCPauseMillis:设置最大垃圾停顿时间。例:-XX:MaxGCPauseMillis=200
  4. -XX:GCTimeRatio:设置吞吐量大小。取值范围为 0~100 的整数。若值为 n,那么 JVM 将花费不超过 1/(1+n) 的时间在 GC 上。例:-XX:GCTimeRatio=99
  5. -XX:+UseAdaptiveSizePolicy:自适应调整 新生代大小、eden 和 survivor 比例,以及晋升老年代对象年龄等参数
  6. 可经过 -XX:+UseParallelGC、-XX:+UseParallelOldGC 启用
  7. GC 日志以下
[GC (Allocation Failure) [PSYoungGen: 2410K->512K(4608K)] 12650K->10947K(19968K), 0.0016662 secs] [Times: user=0.01 sys=0.00, real=0.01 secs] 
复制代码

ParallelOldGC

  1. 老年代垃圾回收器,使用 标记-压缩算法
  2. 与 ParallelGC 一致,关注系统吞吐量,ParallelOldGC 在 jdk1.6后(包括) 才可使用
  3. -XX:ParalleGCThreads:设置 GC 时,并行的线程数
  4. 可经过 -XX:+UseParallelGC、-XX:+UseParallelOldGC 启用
  5. GC 日志以下
[Full GC (Allocation Failure) [PSYoungGen: 480K->0K(4608K)] [ParOldGen: 10499K->626K(15360K)] 10979K->626K(19968K), [Metaspace: 3063K->3063K(1056768K)], 0.0043604 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 
复制代码

CMS

CMS 是一款 低停顿 的 老年代 垃圾收集器。通常与 Serial, ParNew 新生代收集器一块儿工做,默认是 ParNew。 工做流程细化为如下几个步骤多线程

  1. 初始化标记(stop the world)
  2. 并发标记
  3. 预清理
  4. 从新标记(stop the world)
  5. 并发清理
  6. 并发重置状态等待下次 CMS 触发

初始化标记

  1. stop the world
  2. 标记老年代 GC Root 对象
  3. 标记新手代引用老年代的对象

并发标记

  1. 与应用线程并发执行,从上一步标记的节点顺着引用链路往下标记
  2. 并发标记过程当中,老年代会产生新的对象、老年代引用会变动等等。为了提升从新标记的效率,这些对象所在的 card 会被标记为 dirty。
  3. 这一阶段,可能会致使 concurrent mode failure

预清理

与应用线程并发执行,处理上一个阶段被标记为 dirty 的对象。该阶段为了减小 从新标记 产生的停顿时间,有可能会等待一次 ygc并发

从新标记

  1. stop the world
  2. 从 dirty 和 root 继续往下标记可达对象

并发清理

  1. 与应用线程并发执行
  2. 采用 标记-清除 算法将垃圾清除

concurrent mode failure

在并发清理阶段,提到,有可能会发生 concurrent mode failure 现象。 出现该现象的本质缘由以下: 老年代没有足够的空间分配对象,从而致使使用 Serial Old 垃圾收集器触发一次 Full GCide

主要参数

  1. -XX:ConcGCThreads, -XX:ParallelCMSThreads

CMS 默认启动的并发线程是(ParallelGCThreads + 3)/ 4. ParallelGCThreads 表示新生代 GC 线程数量。-XX:ConcGCThreads -XX:ParallelCMSThreads 可手动指定 CMS 并发线程 2. -XX:+CMSScavengeBeforeRemark 在进行 从新标记 阶段时,会执行一次 ygc3. -XX:CMSInitiatingOccupancyFraction 默认68,当老年代空间使用率达到该值时,会执行一次 CMS GC4. -XX:+UseCMSCompactAtFullCollection 使 CMS 在垃圾收集完成后,进行一次内存碎片整理,碎片整理会 stop the world。 5. -XX:CMSFullGCsBeforeCompaction 默认0,设定进行多少次 CMS 回收后,进行一次内存压缩 6. -XX:CMSMaxAbortablePrecleanTime 默认 5000 毫秒,预清理阶段,等待 ygc 最大时间 7. -XX:+CMSClassUnloadingEnabled 容许回收 Class性能

垃圾回收器组合

笔者没法在 jdk1.8 上,测试出 serial + parallel old 组合。测试

参考

CMS垃圾收集器spa

相关文章
相关标签/搜索