Java垃圾回收以可达性分析为核心,从GC Roots出发标记存活对象;堆分新生代(Eden+Survivor)和老年代,依对象寿命差异化管理;新生代用复制算法,老年代用标记-清除或标记-整理;收集器从Serial演进至ZGC,追求低延迟。

Java 垃圾回收(GC)的核心,是自动识别并释放堆中“不可达”的对象所占内存,无需开发者手动干预。它不是靠计数或猜测,而是以可达性分析为判断依据,结合分代管理与多种回收算法协同工作。
对象存活判定:从 GC Roots 开始追踪
JVM 不依赖引用计数(易被循环引用误导),而是采用可达性分析算法:从一组可信的起始点(GC Roots)出发,沿引用链向下搜索。所有能被遍历到的对象视为“存活”,其余即为可回收垃圾。
常见的 GC Roots 包括:
- 虚拟机栈中局部变量引用的对象
- 方法区中静态变量引用的对象
- 方法区常量池中字符串常量引用的对象
- 本地方法栈中 JNI 引用的对象
堆内存分代:按对象寿命差异化治理
JVM 将堆划分为新生代和老年代,比例通常为 1:2,背后是弱分代假说——98% 的对象朝生夕死。
立即学习“Java免费学习笔记(深入)”;
新生代进一步细分为:
- Eden 区:新对象默认分配地
- Survivor 区(From / To):存放经历一次 Minor GC 后仍存活的对象,年龄+1;达到阈值(默认15)晋升至老年代
老年代存放长期存活对象,触发 Major GC(或 Full GC)时才清理,频率低但耗时长。
主流 GC 算法:各司其职,不搞一刀切
不同区域采用不同策略,本质是权衡空间、时间与碎片:
- 复制算法:用于新生代。Eden + 一个 Survivor 区作为“使用区”,另一个为“空闲区”;GC 时将存活对象复制过去,清空原区。优点是无碎片、执行快;缺点是浪费一半空间
- 标记-清除算法:用于老年代初期或部分收集器。先标记存活对象,再清除未标记区域。简单但会产生内存碎片,影响大对象分配
- 标记-整理算法:在标记-清除基础上增加“整理”步骤,将存活对象向一端压缩,消除碎片。适合老年代,代价是移动开销
回收器演进:从 Serial 到 ZGC,目标始终是低延迟
HotSpot JVM 提供多种垃圾收集器,它们是对上述算法的具体实现:
- Serial / Parallel:单线程/多线程,Stop-The-World 时间明显,适合小应用或服务端后台任务
- CMS(已弃用):以低停顿为目标,并发标记清除,但有浮动垃圾和内存碎片问题
- G1:面向服务端,分区(Region)设计,兼顾吞吐与响应,可预测停顿时间
- ZGC / Shenandoah:超低延迟(毫秒级停顿),支持 TB 级堆,通过着色指针或读屏障实现并发处理


















