JVM 04 gc 垃圾回收机制

2016/07/14 JVM 共 2962 字,约 9 分钟
MiniPa

1.GC 内存自动管理

1.栈帧随着入栈和出栈,实现了自动内存管理
2.gc 主要集中于 Java堆方法区

gc11

2.对象存活判断

  • 1.引用计数,无法解决循环引用

  • 2.可达性分析 Reachability Analysis

引用链,从GC Roots向下搜索,搜索路径为引用链
一个对象不在任何一条引用链中,对象不可用,不可达

GC Roots:

1.虚拟机栈中引用的对象
2.方法区静态属性实体引用的对象
3.方法区常量引用的对象
4.本地方法栈中JNI引用的对象

3.GC分代收集理论:

  • 弱分代假说(Weak Generational Hypothesis):绝大多数对象都是朝生夕灭的

  • 强分代假说(Strong Generational Hypothesis):熬过越多次垃圾收集过程的对象就越难以消亡

  • 跨代引用假说(Intergenerational Reference Hypothesis):跨代引用相对于同代引用来说仅占极少数

1.Eden: 新创建对象存放这里(一些大对象特殊处理)

Eden:From:To = 8:1:1
Eden中对象经过第一次 MinorGC后。存活则1岁,进入From,然后在Survivor中年龄逐渐增加,一定程度后,移动到老年代
YoungGeneration(80%以上朝生夕死,采用 Copying 算法)

gc12

2.gc开始时,To区空,Eden存活的全部到To区,From年龄大的到Old,没有的到To区,然后From清空,From和To交换角色

gc13

4.常用收集器组合

YongOld说明
SerialSerial Old全单线程,GC暂停所有应用线程
SerialCMS + Serial Old**CMS **无需 STW,CMS 失败自动用 Serial Old
ParNewCMS默认 GC线程数为 CPU数量,可指定
ParNewSerial Old 
Parallel ScavengeSerial Old关注可控吞吐量,尽可能提高CPU利用率,适用于持久后台运行的程序,不适合交互较多的程序
Parallel ScavengeParallel Old 
G1GCG1GC良好

5.垃圾收集算法

  • MS: 标记、清除算法 MS Mark-Sweep,是最基础的收集算法
    标记和清除效率都不高,会产生大量碎片空间

  • Copy: 复制 Copying 内存分两块,一次用一半,清理时复制到另一半
    实现简单,运行高效,但缩小了内存,持续复制长期生存对象降低效率

  • MC: 标记、压缩 MC Mark Compact,标记后所有对象像一边移动,清理掉边界外内容

  • GC: 分代收集,GC Generation Collection 基于假设绝大部分对象生命周期都非常短
    Yong:每次都有大量对象死去,所以采用Copying复制算法
    Old:对象存活率高,采用MS、MC都可以

6.垃圾收集器 算法的具体实现

1.串行 Serial GC

最古老最稳定效率高的收集器,可能产生较长的停顿,只用一个线程去回收
Yong、Old用Serial,Yong-Copying、Old-Compact,gc过程可能会产生服务暂停
-XX:+UserSerialGC 是默认垃圾收集器,适合单CPU

gc1

2.并行 ParNew,是Serial多线程版本

Yong 并行 + Copying、Old 串行+MC
-XX;+UserParNewGC
-XX:ParallelGCThreads=4 限制线程数量

Parallel Scavenge 类似 ParNew,更关注系统吞吐量,可通过参数打开自适应调节策略,虚拟机会检测系统运行情况,自动调整参数,提供合适的停顿时间,或最大吞吐量

Yong-Copying、Old MC
Parelle Old,使用多线程和MC算法
-XX:ParallelOldGC 使用Parallel收集器 + Old并行

gc2

3.CMS Concurrent Mark Sweep, 并发收集器

以获取最短停顿时间为目标的收集器
适合尤其注重服务的响应速度,希望系统停顿时间最短,给用户较耗体验上

1.初始标记 CMS initial mark,标记 GC Roots能直接关联的对象,速度快
2.**并发标记** CMS concurrent mark,GC Root Tracing过程
3.重新标记 CMS remark,修正并发期间,用户持续运作造成的变动部分
4.**并发清除** CMS concurrent sweep

gc3

1.2步骤仍需stop the world,
2,4是耗时最长的步骤,但收集器线程和用户线程可以一起工作
总体看用户线程和FC内存回收过程一起并发执行

优点:并发收集,低停顿
缺点:产生大量碎片空间,并发阶段会降低吞吐量

-XX:+UseConcMarkSweepGC 使用CMS收集器
-XX:+ UseCMSCompactAtFullCollection Full GC后,进行一次碎片整理;

整理过程是独占的,会引起停顿时间变长

-XX:+CMSFullGCsBeforeCompaction 设置进行几次Full GC后,进行一次碎片整理
-XX:ParallelCMSThreads 设定CMS的线程数量(一般情况约等于可用CPU数量)

4.G1 收集器 Grabage First垃圾优先
-XX:+**UnlockExperimentalVMOptions** -XX:+UseG1GC #开启
-XX:MaxGCPauseMillis = 50 # 暂停时间目标
-XX:GCPauseIntervalMillis = 200 # 暂停间隔目标
-XX:+G1YongGenSize = 512m # 年轻代大小
-XX:SurvivorRatio =6 # 幸村区比例

1.空间整合,MC不会产生内存碎片
2.可预测停顿,可指定消耗在垃圾收集上的时间不超过N毫秒,几乎达到实时Java(RTSJ)的垃圾收集器特征了
3.G1将整个Java堆划分为大小相等的独立区域Region,Yong和Old不再是物理隔阂了,它们都是一部分Region的集合

gc4

G1新生代收集器和Parallel相似,Yong占用达到一定比例,开始GC, 老年代和CMS类似,Old收集会有短暂的停顿

收集步骤:

  • 1.标记 initial mark,会有 Stop-the-world-event,会出发一次普通 Mintor GC,对应GC log:GC pause(yong)(initial-mark)
  • 2.Root Region Scanning,会回收survivor区(存活到老年代),这一过程必须在yongGC前完成
  • 3.Concurrent Marking 在整个堆中进行并发标记,此过程可能会被yong GC打断, 并发标记会计算区域活性,活性为0,会立即回收

gc5

  • 4.Remark 再标记,会有短暂停顿(STW),采用了比CMS中更快的初始快照算法:snapshot-at-the-beginning(SATB)

  • 5.Copy/Clean up,多线程清除失活对象,会有STW,G1将回收区域的存活对象copy到新区域,清除Remember Sets,并发清空回收区域并把它返回到空闲区域链表中

gc6

  • 6.复制/清除过程后,回收区域的活性对象,以集中到如下的深蓝和深绿色区域

gc7

参考:

1.JVM类加载机制

2.JVM内存结构

3.GC算法

4.JVM调优–命令

5.Java GC分析

6.Java GC调优案例

7.JVM调优–工具

8.JVM知识点总览

9.如何优化JavaGC

10.OOM Killer

文档信息

Search

    Table of Contents