JVM堆内存分代模型核心是按对象生命周期差异化管理,划分为年轻代(Eden+S0/S1)和老年代,分别采用复制算法与标记-整理/清除算法;分代设计源于实际对象存活规律,源码中从GenCollectedHeap到G1/ZGC体现分代思想的演进。

Java 源码解析中,JVM 堆内存的分代模型与垃圾回收算法演进,核心在于“按对象生命周期差异做差异化管理”——不是所有对象都该用同一种方式回收,而是根据存活时间长短,把堆划成不同区域,并为每个区域匹配最合适的回收策略。
堆内存的分代结构:年轻代与老年代的分工
现代 HotSpot JVM 将堆划分为年轻代(Young Generation)和老年代(Old Generation),元空间(Metaspace)已独立于堆外,不参与 GC。
-
年轻代:包含 Eden 区 + 两个 Survivor 区(S0/S1)。绝大多数新对象在此分配;Eden 区满时触发 Minor GC,存活对象被复制到 Survivor 区,年龄+1;默认年龄达 15 即晋升至老年代(可通过
-XX:MaxTenuringThreshold调整)。 -
老年代:存放长期存活对象、大对象(如大数组,可能直接分配到老年代,由
-XX:PretenureSizeThreshold控制)以及从年轻代晋升的对象。当老年代空间不足,触发 Major GC 或 Full GC,耗时远高于 Minor GC。
垃圾回收算法的演进逻辑:从通用到场景适配
JVM 并未采用单一算法,而是依据分代特性,组合使用不同算法:
- 年轻代用复制算法:因对象死亡率高(约 90% 一次即死),只需复制少量存活对象到空闲 Survivor 区,效率高、无碎片。但代价是牺牲一半可用空间(实际通过动态调整 Survivor 大小缓解)。
- 老年代用标记-整理或标记-清除:对象存活率高,复制成本过高。CMS 曾用标记-清除(低延迟但产生碎片),G1 和 ZGC 则转向标记-整理或基于区域的增量回收,兼顾吞吐与响应性。
- 不采用引用计数法:虽实现简单,但无法处理循环引用,且每次赋值需原子更新计数器,开销大,Java 规范明确弃用。
分代设计背后的现实依据
分代不是凭空划分,而是对真实应用行为的建模:
立即学习“Java免费学习笔记(深入)”;
- 方法内创建的临时对象(如 StringBuilder、局部集合)通常在方法退出后立即不可达;
- Spring Bean、缓存容器、连接池等长生命周期对象稳定驻留;
- 分代让 GC 可以“高频快扫”年轻代(毫秒级),而“低频精扫”老年代(百毫秒~秒级),大幅降低整体停顿压力。
从源码角度看演进痕迹
OpenJDK 源码中,CollectedHeap 是堆的顶层抽象,GenCollectedHeap 实现分代模型,而 G1CollectedHeap 和 ZCollectedHeap 则逐步弱化传统分代边界——G1 用分区(Region)模拟分代,ZGC 甚至取消分代概念,转为并发标记+染色指针,体现的是“分代思想仍在,实现形式迭代”的本质。


















