外观
一句话答案
三种基础算法:标记-清除(碎片)、复制(浪费空间)、标记-整理(移动开销),分代收集结合使用。
核心要点
三种基础算法:
1. 标记-清除(Mark-Sweep)
阶段1 标记:从 GC Root 出发,标记所有可达对象
阶段2 清除:回收未被标记的对象(不可达对象)
内存布局示意(O=存活, X=待回收, _=空闲):
回收前:[O][X][O][O][X][X][O]
回收后:[O][_][O][O][_][_][O] ← 碎片化!- 优点: 实现简单,不移动对象
- 缺点: ① 产生大量内存碎片,大对象分配困难 ② 需要维护空闲链表,分配效率低
2. 标记-复制(Mark-Copy)
将内存分为两半(from 区 / to 区)
标记:标记 from 区存活对象
复制:将存活对象紧密地复制到 to 区
清空 from 区,交换 from 和 to 角色
from:[O][X][O][O][X][X][O]
to(复制后):[O][O][O][O]______ ← 无碎片!- 优点: 无内存碎片,分配简单(指针碰撞)
- 缺点: 内存利用率只有 50%;存活对象多时复制开销大
JVM 年轻代用的是改进版复制算法(Eden:S0:S1 = 8:1:1):
- 每次只有 10% 空间(一个 Survivor)闲置,而不是 50%
- Minor GC 后存活率低,复制开销小,非常适合
3. 标记-整理(Mark-Compact)
标记:标记所有存活对象
整理:将存活对象向一端移动,然后直接清除边界以外的内存
整理后:[O][O][O][O]___________ ← 无碎片,利用率100%- 优点: 无内存碎片,内存利用率高
- 缺点: 移动对象需要更新所有引用(Stop-The-World 时间长),开销大
老年代通常用标记-整理或标记-清除(CMS 用标记-清除,G1 整体用标记-整理)。
追问与易错
追问方向:
- 什么是 GC Roots?(虚拟机栈引用/静态变量/常量/JNI 引用)
- 为什么新生代用复制算法?(新生代对象朝生夕灭,存活率低,复制开销小)
- 三色标记法是什么?(白/灰/黑标记并发遍历对象图)
易错点:
- ❌ "引用计数法是 JVM 使用的"——JVM 使用可达性分析,引用计数有循环引用问题
- ❌ 混淆 Minor GC / Major GC / Full GC 的范围
💡 记忆锚点
三种收拾房间法:标记-清除(扔垃圾但不整理,满地碎片)、标记-复制(搬到新房只带有用的,浪费一半房间)、标记-整理(把东西推到一边腾出整块空间,但搬东西累)。年轻代用复制(东西少搬得快),老年代用整理或清除。