JVM垃圾回收(GC)深度解析:原理、调优与问题排查
在Java开发中,垃圾回收(GC)是JVM自动内存管理的核心机制,它解放了开发者手动管理内存的负担,但也带来了新的挑战——当GC行为异常时(如频繁YGC、Full GC、GC停顿过长等),可能导致应用性能急剧下降甚至服务中断。本文将从GC的基本原理出发,深入解析常见GC问题的排查思路与解决方案。
一、JVM垃圾回收核心原理
1.1 什么是垃圾回收?
垃圾回收是JVM自动识别并释放"无用对象"所占用内存的过程。"无用对象"指的是不再被任何存活对象引用的对象,这些对象占据的内存若不及时释放,最终会导致OOM(OutOfMemoryError)。
1.2 内存区域与GC的关系
JVM堆内存是GC的主要工作区域,其内部划分为不同区域,各区域的GC策略不同:
内存区域 | 存储内容 | GC类型 | 特点 |
---|---|---|---|
新生代(Young Gen) | 新创建的对象 | Minor GC(YGC) | 回收频繁,速度快 |
老年代(Old Gen) | 存活较久的对象 | Major GC/Full GC | 回收频率低,耗时较长 |
元空间(Metaspace) | 类信息、常量、静态变量等 | 极少触发 | JDK8+取代永久代,默认无上限(受限于物理内存) |
分代思想:基于"大部分对象存活时间短"的统计规律,新生代采用高效的复制算法,老年代采用标记-整理算法,实现不同区域的针对性优化。
1.3 垃圾回收的核心步骤
无论哪种GC算法,核心流程均可概括为三步:
-
标记(Mark):识别内存中哪些对象是"存活"的(被引用),哪些是"垃圾"(未被引用)。
- 实现方式:可达性分析(以GC Roots为起点,遍历对象引用链,不可达对象标记为垃圾)。
- GC Roots包括:虚拟机栈中引用的对象、方法区中类静态属性引用的对象、常量引用的对象等。
-
清除(Sweep):删除标记为垃圾的对象,释放内存空间。
-
整理(Compact):将存活对象向内存一端移动,消除内存碎片(老年代常用,新生代一般不整理)。
1.4 常见垃圾收集器
JVM提供了多种垃圾收集器,各有适用场景:
收集器 | 特点 | 适用场景 |
---|---|---|
Serial GC | 单线程回收,简单高效但停顿长 | 单CPU、小型应用 |
Parallel GC | 多线程回收,注重吞吐量 | 批处理、后台任务 |
CMS(Concurrent Mark Sweep) | 并发回收 |