jvm高效垃圾回收依赖分代假设、算法匹配与收集器协同:新生代用复制算法处理短命对象,老年代用标记-整理或标记-清除应对长期存活对象,通过分代收集降低停顿时间,现代收集器在此基础上叠加并发等优化。

JVM 实现高效垃圾回收,核心在于分代假设 + 算法匹配 + 收集器协同,不是靠某一种算法单打独斗,而是根据对象生命周期特征,把内存划成不同区域,再为每个区域选最合适的回收策略。
新生代用复制算法,专治“短命对象”
新生代里 98% 的对象存活时间极短(比如方法内创建的临时变量)。复制算法正适合这种场景:
- 把新生代划为 Eden(80%)+ 两个 Survivor 区(各 10%,From 和 To)
- GC 时只扫描 Eden 和 From 区中存活的对象,全部复制到 To 区
- 清空 Eden 和 From,然后交换 From/To 角色
这样做的好处是:只遍历存活对象(少)、复制一次就完成清理、回收后内存连续无碎片、分配新对象只需移动指针(Bump-the-pointer),速度极快
老年代用标记-整理或标记-清除,应对“长期存活”
对象在新生代经历多次 GC 后仍存活,就会晋升到老年代。这里对象多、存活率高,复制成本太大,所以改用:
- 标记-整理:先标记所有可达对象,再把它们向内存一端紧凑排列,清空边界外空间 → 解决碎片问题,不浪费内存
- 标记-清除(如 CMS 早期阶段):标记后直接清理,速度快但留碎片;需配合空闲链表管理,适合对延迟敏感但能容忍碎片的场景
分代收集让整体效率翻倍
JVM 不对整块堆做统一扫描,而是:
- 频繁触发小范围的 Young GC(只处理新生代,毫秒级)
- 少量触发耗时较长的 Old GC(只在老年代空间不足或晋升失败时才发生)
- 全堆 GC(如 Full GC)仅作为兜底,尽量避免
这种“按需分区、按区施策”的方式,大幅降低单次 GC 停顿时间和 CPU 开销
现代收集器进一步优化执行模型
比如 G1 把堆划成多个 Region,优先回收垃圾最多的区域(Garbage-First);ZGC 和 Shenandoah 引入并发标记与并发移动,把大部分工作放到应用线程运行时完成,停顿控制在几毫秒内。它们不是替换基础算法,而是在复制、标记、整理之上叠加并发、增量、局部化等工程优化。











