← 返回软件技术总览 软件技术 · 知识点深化 · 垃圾回收:GC Roots、标记清除/复制/整理、CMS/G1/ZGC
知识点深化 · JVM · 垃圾回收

垃圾回收:GC Roots、标记清除/复制/整理、CMS/G1/ZGC

GC 自动回收堆中不再被引用的对象。它先从 GC Roots 出发标记存活对象,再用不同算法回收死对象;分代假设下新生代用复制、老年代用标记整理。CMS、G1、ZGC 是三代经典收集器。这一页把判断、算法、收集器讲透。

① 小白第一课怎么学(4 步走,约 60 分钟)

别急着背代码,先按这四步建立直觉:

1看图建立直觉(10 分钟)
读②③:GC 怎么找活对象。
2记算法与分代(15 分钟)
读④:标记清除/复制/整理,新生代老年代。
3手推回收(20 分钟)
精读⑤。
4刷题纠错(15 分钟)
做⑦⑩,错题回⑥。
本课小目标学完你要能:① 说什么对象可回收;② 对比三种基础算法;③ 讲清 G1 和 ZGC 的特点。

② 一图看懂:GC 全地图

垃圾回收 GC 判断存活 GC Roots 可达性分析 三种基础算法 清除/复制/整理 分代收集 新生代复制/老年代整理 收集器 CMS / G1 / ZGC STW 停顿,G1 可预测停顿 ZGC 亚毫秒级 易错:引用计数不能解循环引用 可达性分析才行
读法:中心是垃圾回收,上是判断存活,中是算法,下是收集器与易错。

③ 本质直觉:从 GC Roots 出发,够得到的活着,够不到的回收

怎么判断垃圾:从 GC Roots(栈里局部变量、静态变量、常量等)出发沿引用链走,能到达的对象是活的,到不了的是死的。这叫可达性分析。(引用计数法解决不了循环引用,Java 不用。)

三种回收算法:① 标记-清除:标记死对象直接清,产生碎片;② 复制:存活对象拷到另一半,无碎片但浪费一半空间,适合新生代(存活率低);③ 标记-整理:存活对象往一端挪,无碎片但慢,适合老年代。

分代:新对象朝生夕死 → 新生代用复制;老对象活得久 → 老年代用标记整理。

可达性分析:从 Roots 出发 Root A B C D 绿=可达存活(Root→A→B) 红=不可达垃圾(C、D)→回收 新生代存活率低用复制;老年代用整理
STWGC 时要暂停所有应用线程(Stop The World),否则引用关系还在变。G1/ZGC 的目标就是缩短这个停顿。

④ 完整体系与对比表

三种算法对比

算法做法优点缺点
标记-清除标记死对象直接清简单内存碎片
复制存活对象拷到另一半无碎片、快浪费一半空间
标记-整理存活对象挪到一端无碎片移动开销大、慢

分代与收集器

新生代(Eden + 2 Survivor):新对象先进 Eden,Minor GC 时存活对象复制到 Survivor,年龄每次+1,达到阈值(默认15)进老年代。用复制算法。

老年代:存存活久的对象,满了触发 Full GC,用标记-整理。

收集器特点
CMS低停顿并发标记清除,老年代,有碎片
G1Region 化,可预测停顿,JDK9+ 默认
ZGC着色指针/读屏障,停顿 <10ms,超大堆

⑤ 用法场景与典型例题

例1(GC Roots)下列哪个不能当 GC Roots?
栈局部变量、静态变量、常量可以。
GC Roots 包括虚拟机栈局部变量、方法区静态变量、常量、JNI 引用。答案:堆里普通对象互相引用不能当 Root(那是引用链不是起点)。
例2(算法选择)新生代存活率低用哪种?
复制划算。
存活少则拷贝量小,复制算法无碎片。答案:复制算法。
例3(停顿)G1 相比 CMS 的优势?
Region 化可预测停顿。
G1 把堆切成多个 Region,优先回收垃圾多的 Region,可设定 -XX:MaxGCPauseMillis。答案:可预测停顿、无碎片。
做题心法新生代→复制,老年代→整理;低延迟大堆→G1/ZGC;面试先问 STW 停顿。

⑥ 高频错误诊断(4 条)

错误1:用引用计数判断垃圾循环引用 A↔B 计数都不为 0,永远回收不掉。Java 用可达性分析。
错误2:以为 GC 只回收新生代老年代满了也会 Full GC 回收整个堆。
错误3:认为 CMS 没碎片CMS 是标记-清除,会产生碎片,最后不得不标记整理。
错误4:把 Minor GC 和 Full GC 混Minor GC 只回收新生代快;Full GC 回收整堆慢,要尽量避免。

⑦ 考点真题演练(4 题)

考点分布

考法出题形式应对
判断垃圾用什么方法GC Roots 可达性分析
算法新生代/老年代各用啥复制/整理
收集器G1/ZGC 特点可预测停顿/超低延迟
STWGC 为什么停顿引用关系在变

真题基础1. Java 判断对象可回收使用?

真题中档2. 新生代通常使用哪种回收算法?

真题中档3. G1 收集器的核心优势是?

真题拔高4. 关于循环引用 A↔B(无外部引用),可达性分析会怎样?

⑧ 必背知识点卡

判断:GC Roots 可达性分析 解决循环引用
清除:直接清死对象 有碎片
复制:存活拷另一半 新生代
整理:存活挪一端 老年代无碎片
分代:新生代 Eden+Survivor 年龄15 升老年代
收集器:CMS/G1/ZGC G1 可预测停顿
STW:GC 暂停应用 越短越好

⑨ 应用输出:优化一次频繁 Full GC 的服务

场景:大促时服务频繁 Full GC,接口 RT 飙升。
① 看日志:加 -Xlog:gc 看 GC 频率和停顿,发现 Full GC 频繁。
② 定位:dump 堆,发现大集合(如缓存)只增不减——内存泄漏或堆太小。
③ 调参数:选 G1 收集器,设 -XX:MaxGCPauseMillis=200 控制停顿。
④ 修泄漏:给缓存加过期/上限,避免老年代被撑满。
⑤ 效果:Minor GC 为主,Full GC 降到每天一两次。
口述思路合上书说:"频繁 Full GC 先 dump 找泄漏大对象,再选 G1 控停顿。"

⑩ 分层练习(基础 + 中档 + 拔高)

▍基础 6 题

基础1Java 用什么判断垃圾?
GC Roots 可达性分析。
基础2新生代用什么算法?
复制。
基础3老年代用什么算法?
标记-整理。
基础4GC Roots 是什么?
栈局部变量、静态变量等起点。
基础5Minor GC 回收哪?
新生代。
基础6STW 是什么?
GC 时暂停应用线程。

▍中档 6 题

中档7为什么引用计数被淘汰?
解决不了循环引用。
中档8Survivor 区有几个?
两个,from/to 交替。
中档9对象几岁进老年代?
默认 15(-XX:MaxTenuringThreshold)。
中档10G1 把堆分成什么?
多个等大 Region。
中档11ZGC 目标停顿?
亚毫秒级(<10ms),支持超大堆。
中档12标记-清除缺点?
内存碎片。

▍拔高 6 题

拔高13什么是空间分配担保?
新生代放不下时直接进老年代。
拔高14三色标记是什么?
黑(活)、灰(待扫)、白(未扫/垃圾),并发标记基础。
拔高15什么是记忆集 Card Table?
记录老年代引用新生代,避免扫整堆找跨代引用。
拔高16G1 的 Mixed GC 是什么?
同时回收新生代和部分高收益老年代 Region。
拔高17怎么减少 Full GC?
避免大对象直接进老年代、合理堆大小、修内存泄漏。
拔高18逃逸分析干嘛的?
判断对象是否逃出方法范围,可栈上分配减少 GC。

⑪ 记忆口诀 + 7 天复习计划

三句口诀① Roots 出发够着活,够不着的就是垃圾。② 新生代复制老年代整理,G1 控停顿 ZGC 超低延迟。③ 引用计数解不了循环引用,可达性才靠谱。
天任务自检
第 1 天读②③④,画可达性分析能说清 Roots
第 2 天背三算法 + 基础 1-6算法对应对
第 3 天做中档 7-12,说分代过程晋升年龄对
第 4 天做拔高 13-18,讲三色标记能讲清并发
第 5 天做⑦真题 4 题限时每题 2 分钟
第 6-7 天合上书默写算法对比表不看资料全默对

← 返回软件技术总览