9.2 垃圾回收机制
9.2.1 垃圾回收概述
垃圾回收(Garbage Collection, GC)是Java虚拟机(JVM)自动管理内存的核心机制,负责回收不再使用的对象占用的内存空间。Java开发者无需手动释放内存,这大大降低了内存泄漏和指针错误的风险。
主要功能
- 自动内存管理:识别并回收无用对象。
- 内存碎片整理:压缩存活对象以减少内存碎片。
- 分代回收:针对不同生命周期的对象采用不同的回收策略。
9.2.2 垃圾回收的基本原理
对象存活性判断
- 引用计数法(Java未采用):通过计数引用数量判断对象是否存活,但无法解决循环引用问题。
- 可达性分析(Java实际采用):从GC Roots(如栈帧中的局部变量、静态变量等)出发,遍历对象引用链。不可达的对象视为垃圾。
常见的GC Roots
- 虚拟机栈中引用的对象。
- 方法区中静态属性引用的对象。
- 方法区中常量引用的对象。
- 本地方法栈中JNI引用的对象。
9.2.3 分代收集算法
JVM将堆内存划分为不同代(Generations),针对不同代采用不同的回收策略:
1. 年轻代(Young Generation)
- 特点:存放新创建的对象,生命周期短。
- 回收算法:复制算法(Copying)。
- Eden区:对象初次分配的区域。
- Survivor区(S0/S1):存放经过一次GC后存活的对象。
- 触发条件:Eden区满时触发Minor GC。
2. 老年代(Old Generation)
- 特点:存放长期存活的对象(经过多次Minor GC后仍存活)。
- 回收算法:标记-清除(Mark-Sweep)或标记-整理(Mark-Compact)。
- 触发条件:老年代空间不足时触发Major GC(通常伴随Full GC)。
3. 元空间(Metaspace, Java 8+)
- 特点:替代永久代(PermGen),存放类元数据。
- 回收条件:类加载器卸载时回收。
9.2.4 常见的垃圾收集器
JVM提供了多种垃圾收集器,适用于不同场景:
| 收集器 | 作用区域 | 算法 | 特点 |
|---|---|---|---|
| Serial | 年轻代 | 复制算法 | 单线程,适合客户端应用。 |
| Parallel Scavenge | 年轻代 | 复制算法 | 多线程,注重吞吐量。 |
| CMS | 老年代 | 标记-清除 | 低停顿时间,但会产生内存碎片。 |
| G1 | 全堆 | 分区域标记-整理 | 平衡吞吐量与延迟,JDK 9+默认。 |
| ZGC | 全堆 | 并发标记-整理 | 超低停顿(<10ms),JDK 15+生产可用。 |
9.2.5 GC调优建议
常见问题与解决方案
频繁Full GC
- 原因:老年代空间不足或元数据区溢出。
- 解决:增大老年代(
-Xmx)、优化对象生命周期。
长时间停顿(Stop-The-World)
- 原因:CMS或Serial收集器的单线程阶段。
- 解决:切换到G1或ZGC。
内存泄漏
- 排查工具:
jmap生成堆转储,通过MAT或VisualVM分析对象引用链。
- 排查工具:
常用JVM参数示例
# 设置堆大小
-Xms512m -Xmx2g
# 使用G1收集器
-XX:+UseG1GC
# 打印GC日志
-XX:+PrintGCDetails -Xloggc:gc.log
9.2.6 总结
垃圾回收机制是Java高效内存管理的基石,理解其原理和调优方法有助于开发高性能应用。根据应用需求选择合适的收集器,并结合监控工具持续优化,是提升系统稳定性的关键。
