JVM学习之回收器

394 阅读9分钟

一、GC分类与性能指标

主要的性能指标:吞吐量、暂停时间

二、不同的垃圾回收器概述

1、按照运行模式分类

串行回收器Serial 、Serial Old
并行回收器ParNew、Parallel Scavenge 、Parallel Old
并发回收器CMS、G1

2、按照分代去分类垃圾回收器

  • 黑线连接的都是配套使用的
  • Serial Old作为CMS的并发失败的后背方案
  • JDK8默认使用的是Parallel 与Parallel Old的组合回收器
  • JDK9开始引入G1垃圾回收器

3、如何查看默认的垃圾回收器

  • -XX:+PrintCommandLineFlags:查看命令行相关参数
  • jinfo -flag 相关垃圾回收器参数 进程id

三、Serial回收器:串行回收

1、简单说明

Serial回收器:
(1)新生代使用
(2)采用复制算法+串行回收+STW工作模式进行回收
Serial Old回收器:
(1)老年代使用
(2)采用标记压缩+STW工作模式进行回收
(3)可以和Serial回收器配套使用
(4)当CMS回收器并发执行发现出现问题时,需要使用Serial Old回收器

2、如何启用?

  • -XX:+UseSerialGC:这个参数可以指定新生代和老年代使用串行回收器

四、ParNew回收器:并行回收

1、简单说明

ParNew回收器:
(1)新生代使用
(2)与Serial基本一致,Serial的并行版本
(3)采用复制算法+并行执行+STW工作模式回收

2、如何启用?

  • -XX:UseParNewGC
  • -XX:ParallelGCThreads:限制线程个数

五、Parallel回收器:吞吐量优先

1、简单说明

JDK8开始默认的垃圾回收器。

Parallel回收器:
(1)新生代使用
(2)采用复制算法+并行执行+STW工作模式进行回收
那么与上面的ParNew有啥区别?
(1)自适应调节策略
parallel Old回收器:
(1)老年代使用
(2)采用标记压缩算法+并行回收+STW工作模式回收

2、参数设置

  • -XX:UseParallelGC 或者-XX:UseParallelOldGC启用回收器
  • -XX:ParallelGCThreads:设置年轻代并行线程数,线程个数一般参考如下规则:
    • CPU小于8个,线程数与CPU个数一样
    • CPU大于8个,线程数=3+(5*CPU_COUNT/8)
  • -XX:MaxGCPauseMillis:设置回收器的最大停顿时间(STW的时间),毫秒
  • -XX:GCTimeRatio:垃圾收集时间占总时间的比例
  • -XX:UseAdaptiveSizePolicy:设置Parallel回收器的自适应调节策略

六、CMS回收器:低延迟

1、简单介绍

CMS回收器:
(1)老年代使用的,并发的回收器
(2)采用标记压缩算法+并发执行+STW工作模式回收垃圾

2、工作模式

CMS工作模式分为4个阶段。

  • 初始标记:在这个阶段,程序中所有的工作线程都将STW 然后短暂的暂停,这个阶段主要是标记出GC Root直接关联的对象。一旦标记完成就会恢复之前被暂停的所有应用线程。
  • 并发标记:从GC Roots的直接管理对象开始遍历整个对象图的过程,这个过程耗时比较长但是不需要停顿用户线程,可以与垃圾回收线程一起并发执行。
  • 重新标记:由于在并发标记阶段,程序的工作线程会和垃圾回收线程一个工作,因此为了修正并发标记阶段,因为用户线程继续运行而导致标记产生标动的那部分对象的标记记录,这个阶段的停顿时间通常会比初始标记阶段稍长一些,但也远比并发标记阶段的时间短。
  • 并发清除:此阶段清理删除掉标记阶段判断的已经死亡的对象,并释放内存空间。这个阶段不能移动存活对象,所以此时采用标记清除算法。

3、注意点

  • 由于cms在回收阶段要保证用户线程有足够的内存可用,因此cms回收器不能想其他回收器一样等待老年代几乎被占满可再进行回收。而是当堆内存使用到一定阈值时,便开始回收;如果在运行期间没有足够内存,就会出现一次“Concurrent Mode Failure”失败,这时jvm就会启用预备方案,临时使用Serial Old回收器来回收垃圾。

4、优缺点

优点:

  • 低延迟
  • 并发执行

缺点:

  • 会产生内存碎片
  • cms收集器对cpu资源非常敏感。
  • cms收集器无法处理浮动垃圾。在并发标记阶段如果产生新的垃圾对象,cms将无法对这些垃圾进行标记,最终会导致这些新的垃圾不能被及时回收,从而只能在执行下一次GC时释放内存空间。

5、参数设置

  • -XX:+UseConcMarkSweepGC:指定使用cms垃圾回收器
  • -XX:CMSInitiatingOccupanyFraction:设置内存使用率的阈值。

七、G1回收器:区域化分代式

1、简单说明

  • G1把内存分割成物理上可以不连续的区域,使用不同的区域来表示Eden区,S0,S1,老年代。
  • G1有计划的避免在整个堆进行全区域的垃圾回收,G1跟踪各个区域里面的垃圾堆积的价值大小,在后台维护一个优先列表,每次根据允许的收集时间去优先回收价值最大的区域。简单理解就是去回收垃圾量最大的区域。
  • JDK9后默认的回收器

2、特点介绍

  • 并行与并发
    • 并行性:G1在回收时期,可以多个GC线程同时工作,有效利用多核计算能力,此时用户线程STW
    • 并发性:G1拥有与应用程序交替执行的能力,部分工作可以和应用程序同时执行,因此,一般来说,不会在整个回收阶段去阻塞程序。
  • 分代收集:
    • 通过分散在不同区域的分代处理,来说明是一个区别于传统的连续的分代收集。
    • 与之前的回收器不同,G1兼顾新生代和老年代的回收
  • 空间整理避免碎片化:
    • 内存回收是以区域为单位。区域之间是复制算法;但整体上可以看成是标记压缩算法。这两种算法都可以避免碎片化。当堆非常大时,G1的优势更加明显。
  • 可预测的停顿时间模型:
    • 简单理解就是可以去限定一个长度为M的时间片段内,消耗在垃圾回收的时间不超过N。
    • 通过维护最有价值的垃圾,一般理解就是最多,来明确下一次回收时去回收哪个区域,这样可以保证在单位时间内处理的垃圾是最多。

3、参数设置

  • -XX:+UseG1GC :手动指定使用G1
  • -XX:G1HeapRegionSize:设置每个区域的大小。
  • -XX:MaxGcPauseMillis:设置期望的最大停顿时间。
  • -XX:ParallelGCThread:设置STW工作线程的值。
  • -XX:ConcGCThreads:设置并发标记的线程数
  • -XX:InitiatingHeapOccupancyPercent:设置出发并发GC周期的堆占用阈值,超过此值,就发生GC

4、G1回收器回收过程

  1. 年轻代GC--》Minor GC
  2. 并发标记(可以混合Minor GC)
  3. 混合回收--》
  4. 单线程的Full GC--》主要是堆GC评估失败的情况提供失败保护机制,即强力回收
年轻代GC:
(1)一个并行独占的STW过程,和之前学过的Minor GC保持相同的特点
过程如下:
(1)扫描根:根引用连同记忆集记录的外部引用作为扫描存活对象的入口。根一般指static变量指向的对象,正在执行的方法调用连上的局部变量。
(2)更新记忆集:处理dirty card queue中的card,更新记忆集。此阶段完成后,记忆集可以准确的反应老年代对所在的内存分段对象的引用。
(3)处理记忆集:识别被老年代对象指向的Eden中的对象,这些被指向的Eden中的对象被认为是存活的对象。
(4)复制对象:用复制算法进行Minor GC
(5)处理引用:处理软引用、弱引用等引用。
(6)最终,Eden区域内存回收,对象是连续空间上分配,没有碎片。变成空闲的区域。
并发标记过程:
(1)初始标记:与cms的第一个环节一致
(2)根区域扫描:扫描S区直接可达的老年代区域对象,并标记被引用的对象。这个过程必须在Young GC之前完成。
(3)并发标记:在整个堆中进行并发标记,此时可以被young gc中断,在并发标记阶段,若发现区域对象中的所有对象都是垃圾,这个区域会被立即回收。
(4)再次标记:由于程序持续进行,需要修正上一次的标记结果。是一个STW的过程。
(5)独占清理:计算各个区域的存活对象和回收比例,并进行排序,识别可以混合回收的区域。是STW的。
(6)并发清理阶段:识别并清理完全空闲的区域

5、记忆集Remenber Set

当一个对象被不同区域引用时,此时应该如何去判活?是否需要去全堆扫描呢?

  • 为每个区域配备一个记忆集,某个区域的记忆集中记录的是我这个区域引用的其他区域的对象地址。
  • 每次引用类型的数据进行写操作时,都会产生一个写屏障去中断操作,然后去判断是否有跨区域操作,如果有跨区域操作,则通过卡表把引用信息记录到区域对应的记忆集中。在进行垃圾回收时,在GC根节点的枚举范围内加入记忆集,就可以保证不进行全局扫描,也不会有遗漏了。

八、垃圾回收器总结

回收器分类位置算法特点场景
Serial串行新生代复制算法响应速度优先单cpu的client模式
ParNew并行老年代复制算法响应速度优先多cpu的server模式
Parallel并行新生代复制算法吞吐量优先后台运算且不需要太多交互场景
Serial Old串行老年代标记压缩响应速度优先单cpu的client模式
Parallel Old并行老年代标记压缩吞吐量优先后台运算且不需要太多交互场景
CMS并发老年代标记清除响应速度优先使用互联网
G1并发\并行新生代、老年代复制算法、标记压缩响应速度优先服务端