全景解析的核心是理清对象从出生到消亡的整条链路,即基于堆内存分层管理的动态策略体系:按年龄分区(Eden、Survivor、老年代),以GC Roots为起点判断可达性,通过标记-清除/复制/整理回收,并依引用强度(强、软、弱、虚)调控回收时机。

直接看“全景解析”,重点不是背算法名字,而是理清对象从出生到消亡的整条链路。它本质是一套围绕堆内存分层管理的动态策略体系,核心在于“不同生命周期的对象,用不同的方式对待”。
先搞懂对象在堆里怎么“分区生活”
Java堆不是一块平地,而是按对象年龄划成三块:
- Eden区:新对象默认落脚地,像刚入学的新生
- Survivor区(S0/S1):熬过一次GC的幸存者暂住,每次GC后年龄+1
- 老年代:年龄到阈值(默认15)或大对象、动态判定达标者搬入,类似“资深居民”
这种分代不是固定不变的——大对象可能跳过Eden直奔老年代;Survivor空间不够时,部分对象也会提前晋升。理解分区逻辑,比死记“哪些收集器用什么算法”更管用。
判断一个对象该不该回收,只看一件事
不是看它“有没有被new过”,而是看它是否还能被程序访问到。JVM从一组可信起点(GC Roots)出发,顺着引用链往下找:
立即学习“Java免费学习笔记(深入)”;
- 栈帧里的局部变量引用
- 方法区的静态属性、常量池引用
- 本地方法栈的JNI引用
- 被synchronized锁住的对象
只要某对象和任意一个GC Root之间有引用链连通,它就“活着”;断了,就是候选垃圾。注意:循环引用在Java里不构成存活依据,这点和Python不同。
回收过程不止是“删”,还涉及空间整理
一次完整的GC动作通常包含三个阶段:
- 标记(Marking):遍历所有可达对象,打上“活着”标签
- 清除(Sweeping)或复制(Copying):根据区域特点选择策略——Eden和Survivor常用复制算法(快且无碎片),老年代倾向标记-清除或标记-整理(兼顾空间利用率和碎片控制)
- 压缩(Compacting):尤其在Full GC后,把存活对象往一端挪,腾出连续空闲空间,避免分配失败
不同收集器(如Serial、G1、ZGC)只是在这些环节上做了取舍:有的追求低延迟(停顿短),有的专注吞吐量(单位时间处理多),没有万能方案,只有适配场景的选择。
别忽略引用类型对回收时机的影响
Java把“引用强度”分四档,直接影响GC行为:
- 强引用:普通new出来的对象,只要它还被强引用着,就不会被回收
- 软引用:内存不足时才回收,适合做缓存(如图片缓存)
- 弱引用:下次GC就收,适合临时映射(如WeakHashMap)
- 虚引用:唯一用途是配合ReferenceQueue监听对象被回收的时刻,不能用来取对象
写代码时有意选用不同引用类型,相当于给JVM下了“回收优先级指令”,这是开发者能主动参与GC调控的少数接口之一。


















