跳到主要内容

图解Jvm 11.垃圾回收概述及算法

·1601 字·4 分钟

1. 垃圾回收概述 #

1.1 什么是垃圾? #

技术定义: #

在JVM语境中,“垃圾"指失去所有引用的堆内存对象。判定标准:

关键特征: #

  1. 不可达对象(通过GC Roots不可达)
  2. 循环引用孤岛(彼此引用但整体不可达)
  3. 特殊引用(软/弱/虚引用)的次级对象

1.2 为什么需要GC? #

三大核心原因:

  1. 内存安全:防止野指针和非法内存访问
  2. 资源管理:自动回收不再使用的对象
  3. 性能优化:通过内存整理提升访问效率

1.3 早期垃圾回收 #

技术演进路线:

1.4 Java垃圾回收机制 #

核心架构: #

关键特性: #

  1. 自动内存管理:开发人员无需显式释放
  2. 分代假设:弱分代假说/强分代假说
  3. STW机制:安全点(Safepoint)控制

2. 垃圾回收相关算法 #

2.1 标记阶段:引用计数算法 #

实现原理: #

致命缺陷演示: #

循环引用问题:即使对象间互相引用,但因外部引用断开,实际已成为垃圾却无法被识别

2.2 标记阶段:可达性分析算法 #

核心原理: #

GC Roots类型: #

  1. 虚拟机栈中的局部变量
  2. 方法区静态属性引用
  3. 方法区常量引用
  4. 本地方法栈JNI引用
  5. 同步锁持有对象

2.3 对象的finalization机制 #

生存判定流程: #

重要特性<font style="background-color:rgb(252, 252, 252);">finalize()</font>方法只会被JVM调用一次,且不保证执行顺序

2.4 MAT与JProfiler的GC Roots溯源 #

实战操作流程: #

JProfiler溯源示例: #

2.5 清除阶段:标记-清除算法 #

执行过程详解: #

  1. 标记阶段:通过可达性分析标记所有存活对象
  2. 清除阶段:线性遍历堆内存,回收未被标记的对象块

缺陷分析: #

技术痛点: #

  • 两次全堆扫描(标记和清除)效率低
  • 清除后内存空间不连续,导致分配大对象时触发Full GC

2.6 清除阶段:复制算法 #

核心机制: #

  • 内存划分:将可用内存分为两个等大的From和To区域
  • 存活对象迁移:将From区存活对象复制到To区,并保持内存紧凑

优劣对比表: #

优势劣势
无内存碎片内存利用率仅50%
高速分配(指针碰撞)对象存活率高时效率骤降
适合年轻代需要额外空间处理引用更新

实战应用: #


2.7 清除阶段:标记-压缩算法 #

指针碰撞原理: #

适用场景: #

  • 老年代垃圾回收(配合CMS或G1使用)
  • 需要长期存活的大对象管理

性能影响: #


2.8 算法对比总结 #


2.9 分代收集算法 #

内存代际划分: #

回收策略矩阵: #

代际算法触发条件耗时
年轻代复制算法Eden满毫秒级
老年代标记-压缩空间不足秒级

对象晋升流程: #


2.10 增量收集与分区算法 #

增量收集原理: #

分区算法优势: #

3. 垃圾回收常见问题与解决方案 #

3.1 内存泄漏问题 #

典型案例: #

  1. 线程局部变量泄漏:ThreadLocal使用后未remove
  2. 缓存失控增长:Guava Cache未设置过期策略
  3. JNI引用未释放:本地方法分配的内存未回收

3.2 GC性能调优 #

调优决策树: #

参数配置矩阵: #

场景推荐参数作用域
Web应用-XX:+UseG1GC全堆
大数据计算-XX:+UseParallelGC年轻代
低延迟交易-XX:+UseZGCJDK11+

3.3 Full GC频繁触发 #

诊断流程图: #

常见诱因: #

  1. 老年代空间分配担保失败
  2. 元空间/metadata区溢出
  3. System.gc()主动调用

4. 高频面试问题与解答 #

Q1:引用计数算法与可达性分析的本质区别? #

答案要点


Q2:对象自救的可行性及限制? #

技术解析

关键限制

  1. finalize()执行顺序不确定
  2. 自救仅能执行一次
  3. 不推荐生产环境使用

Q3:标记-清除算法导致的内存碎片如何影响系统? #

影响路径

解决方案对比

方案原理副作用
标记-压缩内存滑动整理STW时间增加
空闲列表维护可用块记录分配效率下降

Q4:G1收集器如何实现可预测停顿? #

核心机制

技术亮点

  1. 将堆划分为2048个Region(默认)
  2. 基于回收效益的优先级排序
  3. 使用Remembered Set处理跨代引用

Q5:如何排查OOM问题? #

实战检查清单

关键命令

# 生成dump文件
jmap -dump:format=b,file=heap.hprof <pid>

# 查看对象直方图
jmap -histo <pid>

Q6:ZGC的核心创新点? #

技术突破

适用场景

  • 要求低延迟的金融交易系统
  • 大内存云原生应用
  • JDK15+生产环境