【JVM虚拟机】垃圾回收GC:垃圾回收算法:标记-清除、标记-复制、标记-整理、分代收集(附《思维导图》+《面试高频考点清单》)

在线体验各类最新模型,更有模型 免费Token 额度领取!
立即体验
简介: 本文系统梳理JVM四大垃圾回收算法(标记-清除、标记-复制、标记-整理、分代收集),详解其原理、优劣、适用场景及演进逻辑,并涵盖GC Roots判定、对象晋升、STW机制、收集器对应关系等核心知识点,助力深入理解内存管理与性能调优。

思维导图

JVM垃圾回收算法 系统性知识体系总结

一、垃圾回收基础概念

1.1 垃圾回收的本质

垃圾回收(Garbage Collection, GC)是JVM自动管理内存的核心机制,负责识别并释放不再被使用的内存空间,避免内存泄漏和OOM(OutOfMemoryError)。

1.2 GC解决的三个核心问题

  1. 哪些内存需要回收:判断对象是否存活
  2. 什么时候回收:触发GC的时机
  3. 如何回收:垃圾回收算法的实现

1.3 对象存活判定算法

  • 引用计数法:给对象添加引用计数器,引用+1,引用失效-1,计数器为0则可回收
    • 优点:实现简单,判定效率高
    • 缺点:无法解决循环引用问题(JVM未采用)
  • 可达性分析算法:以"GC Roots"为起点,向下搜索,不可达的对象即为垃圾
    • GC Roots包括:虚拟机栈中引用的对象、方法区中类静态属性引用的对象、方法区中常量引用的对象、本地方法栈中JNI引用的对象
    • JVM主流实现采用此算法

二、四大核心垃圾回收算法详解

2.1 标记-清除算法(Mark-Sweep)

最基础的垃圾回收算法,其他算法均基于此改进而来

执行过程

  1. 标记阶段:遍历所有GC Roots,标记所有存活对象
  2. 清除阶段:遍历堆内存,回收所有未被标记的对象

优点

  • 实现简单,不需要移动对象
  • 适用于存活对象多、垃圾少的场景

缺点

  • 内存碎片化严重:回收后产生大量不连续的内存碎片
  • 分配大对象时可能提前触发Full GC
  • 标记和清除过程效率都不高(需遍历两次堆)

适用场景

  • 老年代垃圾回收的基础
  • 早期JVM版本的默认算法

2.2 标记-复制算法(Mark-Copy)

为解决标记-清除的内存碎片化问题而设计

执行过程

  1. 将内存划分为大小相等的两块区域:From区和To区
  2. 只使用其中一块(From区)进行对象分配
  3. 当From区满时,标记所有存活对象
  4. 将存活对象完整复制到To区,并按顺序排列
  5. 清空整个From区,交换From和To的角色

优点

  • 无内存碎片化:复制后对象连续排列
  • 分配内存时只需移动指针,效率极高
  • 只需要遍历一次存活对象,垃圾多时效率高

缺点

  • 内存利用率低:只能使用一半的内存空间
  • 存活对象多时,复制开销大

改进:Appel式回收

  • 新生代采用"1个Eden区+2个Survivor区"的划分方式(默认比例8:1:1)
  • 每次只使用Eden和一个Survivor区
  • 回收时将存活对象复制到另一个Survivor区
  • 内存利用率提升至90%

适用场景

  • 新生代垃圾回收:因为新生代对象"朝生夕死",存活对象少,复制开销小

2.3 标记-整理算法(Mark-Compact)

结合了标记-清除和标记-复制的优点,解决老年代的内存问题

执行过程

  1. 标记阶段:与标记-清除相同,标记所有存活对象
  2. 整理阶段:将所有存活对象向内存一端移动,按顺序排列
  3. 直接清理掉边界以外的所有内存

优点

  • 无内存碎片化:对象连续排列
  • 内存利用率100%(不需要预留空间)
  • 适合存活对象多的场景

缺点

  • 需要移动对象:STW(Stop-The-World)时间更长
  • 实现复杂,需要更新所有引用地址

与标记-清除的对比

特性 标记-清除 标记-整理
内存碎片 严重
对象移动 不需要 需要
执行效率 中等
内存利用率
适用场景 存活对象少 存活对象多

适用场景

  • 老年代垃圾回收:老年代对象存活时间长,存活对象多

2.4 分代收集算法(Generational Collection)

不是一种独立的算法,而是基于对象生命周期的组合策略

核心思想

  • 根据对象的存活时间将堆内存划分为不同的代
  • 不同代采用不同的垃圾回收算法,以提高整体效率

JVM分代模型

  1. 新生代(Young Generation)

    • 存放新创建的对象
    • 特点:对象生命周期短,存活率低
    • 回收算法:标记-复制算法
    • 回收频率:高,每次回收时间短
    • 分为:Eden区(80%)、Survivor0(10%)、Survivor1(10%)
  2. 老年代(Old Generation)

    • 存放长期存活的对象
    • 特点:对象生命周期长,存活率高
    • 回收算法:标记-清除或标记-整理算法
    • 回收频率:低,每次回收时间长
  3. 方法区/元空间(Method Area/Metaspace)

    • 存放类信息、常量、静态变量等
    • 回收条件苛刻,主要回收废弃常量和无用类
    • 回收频率:极低

对象晋升机制

  • 对象在Survivor区每熬过一次Minor GC,年龄+1
  • 默认年龄达到15岁时晋升到老年代
  • 大对象直接进入老年代(避免在新生代频繁复制)
  • Survivor区空间不足时,部分对象提前晋升

GC类型

  • Minor GC:新生代垃圾回收
    • 触发条件:Eden区满
    • 特点:速度快,STW时间短
  • Major GC:老年代垃圾回收
    • 触发条件:老年代空间不足
    • 特点:速度慢,STW时间长
  • Full GC:整个堆内存的垃圾回收
    • 触发条件:老年代满、方法区满、System.gc()显式调用
    • 特点:STW时间最长,应尽量避免

三、算法演进与组合使用

3.1 算法组合的基本原则

  • 新生代:标记-复制算法(存活对象少,复制开销小)
  • 老年代:标记-清除或标记-整理算法(存活对象多,复制开销大)

3.2 常见垃圾收集器与算法对应关系

收集器 核心算法 特点
Serial 新生代 标记-复制 单线程,简单高效
ParNew 新生代 标记-复制 Serial的多线程版本
Parallel Scavenge 新生代 标记-复制 吞吐量优先
Serial Old 老年代 标记-整理 单线程,作为CMS的后备
Parallel Old 老年代 标记-整理 Parallel Scavenge的老年代版本
CMS 老年代 标记-清除 并发低延迟,有内存碎片
G1 全堆 标记-整理+复制 区域化分代式,可预测停顿
ZGC/Shenandoah 全堆 着色指针+读屏障 超低延迟,几乎无STW

3.3 算法性能对比

算法 标记效率 清除/复制效率 内存利用率 内存碎片 适用场景
标记-清除 严重 存活对象少
标记-复制 存活对象极少
标记-整理 极低 存活对象多
分代收集 通用场景

四、关键概念与注意事项

4.1 Stop-The-World(STW)

  • GC执行时,暂停所有用户线程的现象
  • 所有垃圾回收算法都会产生STW,只是时间长短不同
  • 现代垃圾收集器的核心目标就是缩短STW时间

4.2 安全点(Safepoint)

  • 用户线程执行过程中能够暂停的特定位置
  • GC只能在安全点触发
  • 常见安全点:方法调用、循环跳转、异常跳转

4.3 垃圾回收的性能指标

  • 吞吐量:用户代码执行时间/(用户代码执行时间+GC时间)
  • 延迟:GC导致的STW时间
  • 内存占用:堆内存的使用效率
  • 这三个指标构成"不可能三角",无法同时最优

4.4 常见误区

  • 误区1:System.gc()会立即触发Full GC
    • 实际上只是建议JVM执行GC,JVM可以选择忽略
  • 误区2:新生代GC比老年代GC快
    • 这是因为新生代存活对象少,而不是算法本身更快
  • 误区3:标记-整理总是比标记-清除好
    • 当老年代碎片不多时,标记-清除的STW时间更短

五、总结

垃圾回收算法是JVM内存管理的核心,四种算法各有优劣:

  • 标记-清除:基础但有碎片
  • 标记-复制:无碎片但内存利用率低
  • 标记-整理:无碎片且内存利用率高但STW时间长
  • 分代收集:结合前三种算法的优点,是现代JVM的主流实现

理解这些算法的原理和适用场景,对于JVM调优和排查内存问题至关重要。随着JVM的发展,新的垃圾收集器(如G1、ZGC)不断涌现,但它们的核心思想仍然基于这四种基础算法。


JVM垃圾回收算法 面试高频考点问答清单

(按面试提问频率排序,答案提炼核心得分点,加粗为必背关键词)

一、垃圾回收基础概念

Q1:什么是垃圾回收(GC)?它解决了什么问题?

:GC是JVM自动管理堆内存的核心机制,负责识别并释放不再被使用的内存空间。它解决了三个核心问题:

  1. 哪些内存需要回收(对象存活判定)
  2. 什么时候回收(GC触发时机)
  3. 如何回收(垃圾回收算法实现)

Q2:JVM如何判断一个对象是否存活?

:主流采用可达性分析算法,以"GC Roots"为起点向下搜索,不可达的对象即为垃圾。

  • GC Roots包括:虚拟机栈引用的对象、方法区静态属性引用的对象、方法区常量引用的对象、本地方法栈JNI引用的对象
  • 淘汰了引用计数法(无法解决循环引用问题)

Q3:什么是循环引用?为什么引用计数法无法解决?

:两个对象互相引用对方,导致它们的引用计数器永远不为0。例如:

A a = new A();
B b = new B();
a.b = b;
b.a = a;
a = null;
b = null;

此时两个对象已无法被访问,但引用计数仍为1,永远无法被回收。

二、四大核心垃圾回收算法

Q4:简述标记-清除算法(Mark-Sweep)的执行过程、优缺点和适用场景

  • 执行过程:①标记阶段:遍历GC Roots,标记所有存活对象;②清除阶段:遍历堆,回收所有未标记对象
  • 优点:实现简单,不需要移动对象
  • 缺点内存碎片化严重;标记和清除都需要遍历整个堆,效率不高
  • 适用场景:老年代垃圾回收的基础,适用于存活对象多、垃圾少的场景

Q5:简述标记-复制算法(Mark-Copy)的执行过程、优缺点和适用场景

  • 执行过程:将内存分为大小相等的两块,每次只使用一块;回收时将存活对象完整复制到另一块,然后清空原块
  • 优点无内存碎片化;分配内存只需移动指针,效率极高;垃圾多时效率高
  • 缺点内存利用率低(只能用一半);存活对象多时复制开销大
  • 适用场景新生代垃圾回收(对象朝生夕死,存活少)

Q6:什么是Appel式回收?它解决了什么问题?

:是标记-复制算法的改进,将新生代划分为1个Eden区+2个Survivor区(默认比例8:1:1)。

  • 每次只使用Eden和一个Survivor区
  • 回收时将存活对象复制到另一个Survivor区
  • 内存利用率从50%提升至90%,是现代JVM新生代的标准实现

Q7:简述标记-整理算法(Mark-Compact)的执行过程、优缺点和适用场景

  • 执行过程:①标记阶段:同标记-清除;②整理阶段:将所有存活对象向内存一端移动,按顺序排列;③清理边界外的所有内存
  • 优点无内存碎片化;内存利用率100%
  • 缺点需要移动对象,STW时间更长;实现复杂,需要更新所有引用地址
  • 适用场景老年代垃圾回收(对象存活时间长,存活多)

Q8:标记-清除和标记-整理算法有什么区别?

特性 标记-清除 标记-整理
内存碎片 严重
对象移动 不需要 需要
STW时间 较短 较长
实现复杂度
适用场景 存活对象少 存活对象多

三、分代收集算法

Q9:什么是分代收集算法?它的核心思想是什么?

:不是独立算法,而是基于对象生命周期的组合策略

  • 核心思想:根据对象存活时间将堆划分为不同的代,不同代采用最适合的垃圾回收算法,以提高整体效率
  • 是现代JVM的主流实现

Q10:JVM的分代模型是怎样的?各代采用什么算法?

  1. 新生代:存放新创建的对象,特点是生命周期短、存活率低
    • 划分:Eden(80%) + Survivor0(10%) + Survivor1(10%)
    • 算法:标记-复制算法
    • 回收频率:高,每次时间短
  2. 老年代:存放长期存活的对象,特点是生命周期长、存活率高
    • 算法:标记-清除或标记-整理算法
    • 回收频率:低,每次时间长
  3. 元空间:存放类信息、常量、静态变量等,回收条件苛刻,频率极低

Q11:对象什么时候会晋升到老年代?

  1. 年龄达标:对象在Survivor区每熬过一次Minor GC,年龄+1,默认15岁晋升
  2. 大对象直接晋升:超过阈值的大对象直接进入老年代(避免新生代频繁复制)
  3. 动态年龄判定:Survivor区中相同年龄所有对象大小总和超过Survivor空间的一半,年龄≥该年龄的对象直接晋升
  4. 空间分配担保失败:Minor GC时Survivor区放不下存活对象,直接晋升到老年代

Q12:Minor GC、Major GC和Full GC有什么区别?

  • Minor GC:新生代垃圾回收
    • 触发条件:Eden区满
    • 特点:速度快,STW时间短
  • Major GC:仅老年代垃圾回收
    • 触发条件:老年代空间不足
    • 特点:速度慢,STW时间长
  • Full GC:整个堆(新生代+老年代+元空间)的垃圾回收
    • 触发条件:老年代满、元空间满、System.gc()显式调用、空间分配担保失败
    • 特点:STW时间最长,应尽量避免

四、关键性能与机制概念

Q13:什么是Stop-The-World(STW)?为什么会发生?

:GC执行时,暂停所有用户线程的现象。

  • 原因:GC需要准确标记存活对象,若用户线程同时运行,会导致对象引用关系不断变化,无法准确标记
  • 所有垃圾回收算法都会产生STW,现代收集器的核心目标就是缩短STW时间

Q14:什么是安全点(Safepoint)?

:用户线程执行过程中能够暂停的特定位置。

  • GC只能在安全点触发
  • 常见安全点:方法调用、循环跳转、异常跳转
  • 设计原则:让用户线程不会长时间运行不到安全点

Q15:垃圾回收的三个核心性能指标是什么?它们之间有什么关系?

:三个指标构成GC不可能三角,无法同时最优:

  1. 吞吐量:用户代码执行时间/(用户代码执行时间+GC时间),越高越好
  2. 延迟:GC导致的STW时间,越短越好
  3. 内存占用:堆内存的使用效率,越低越好
  • 吞吐量优先收集器:Parallel Scavenge + Parallel Old
  • 延迟优先收集器:CMS、G1、ZGC

五、常见误区与调优基础

Q16:调用System.gc()会立即触发Full GC吗?

:不会。System.gc()只是建议JVM执行Full GC,JVM可以选择忽略。

  • 生产环境中应避免显式调用System.gc(),可能导致不必要的Full GC

Q17:为什么新生代GC比老年代GC快?

:不是因为标记-复制算法本身更快,而是因为新生代存活对象极少

  • 标记-复制算法只需要处理存活对象,垃圾越多效率越高
  • 老年代存活对象多,无论是标记-清除还是标记-整理,都需要处理大量对象,所以速度慢

Q18:标记-整理算法总是比标记-清除算法好吗?

:不是。

  • 当老年代内存碎片不多时,标记-清除的STW时间更短(不需要移动对象)
  • 当碎片积累到一定程度,无法分配大对象时,才需要执行标记-整理
  • CMS收集器就是平时用标记-清除,碎片过多时用Serial Old做标记-整理作为后备

六、垃圾收集器与算法对应关系

Q19:常见垃圾收集器分别采用什么核心算法?

收集器 核心算法 核心特点
Serial 新生代 标记-复制 单线程,简单高效
ParNew 新生代 标记-复制 Serial的多线程版本
Parallel Scavenge 新生代 标记-复制 吞吐量优先
Serial Old 老年代 标记-整理 单线程,CMS后备
Parallel Old 老年代 标记-整理 Parallel Scavenge老年代版本
CMS 老年代 标记-清除 并发低延迟,有碎片
G1 全堆 标记-整理+复制 区域化分代,可预测停顿
ZGC/Shenandoah 全堆 着色指针+读屏障 超低延迟(<10ms)

Q20:现代垃圾收集器(G1、ZGC)还基于分代思想吗?

  • G1仍然基于分代思想,但采用区域化分代,将堆划分为多个大小相等的Region,每个Region可以动态扮演Eden、Survivor或老年代
  • ZGC和Shenandoah是不分代的全堆收集器,但它们的核心优化思想仍然源于四大基础算法,特别是标记-整理和复制算法

JVM垃圾回收算法 一页纸速记版

加粗为必背关键词,考前3分钟快速过)

一、基础核心

  • GC本质:自动识别并释放无用内存,解决"哪些/何时/如何回收"
  • 对象存活判定
    • 主流:可达性分析(以GC Roots为起点,不可达即垃圾)
    • GC Roots:栈引用、静态属性、常量、JNI引用
    • 淘汰:引用计数法(无法解决循环引用

二、四大核心算法(必考)

算法 核心过程 核心优点 核心缺点 核心适用
标记-清除 标记存活→清除垃圾 简单,不移动对象 内存碎片严重,效率低 老年代基础
标记-复制 分两块→复制存活→清空原块 无碎片,分配快 内存利用率50%,存活多则复制贵 新生代(朝生夕死)
标记-整理 标记存活→移到一端→清理边界 无碎片,利用率100% 需移动对象,STW更长 老年代(存活多)
分代收集 按存活时间分代→各代用最优算法 综合效率最高 实现复杂 现代JVM主流
  • Appel式回收:新生代8:1:1(Eden+2Survivor),利用率90%,标准实现

三、分代收集核心

  • 新生代:Eden(80%)+S0(10%)+S1(10%),标记-复制,Minor GC频繁且快
  • 老年代:长期存活对象,标记-清除/整理,Major GC慢且少
  • 对象晋升:年龄15岁、大对象、动态年龄判定、空间担保失败
  • GC类型
    • Minor GC:Eden满→新生代→STW短
    • Full GC:老年代/元空间满→全堆→STW最长,尽量避免

四、关键机制

  • STW:GC暂停所有用户线程,所有算法都有,目标是缩短时间
  • 安全点:GC只能在此触发(方法调用、循环、异常)
  • GC不可能三角吞吐量、延迟、内存占用无法同时最优
    • 吞吐量优先:Parallel组合
    • 延迟优先:CMS、G1、ZGC

五、收集器与算法对应

收集器 核心算法 核心特点
Serial/ParNew 新生代 标记-复制 单/多线程
Parallel Scavenge 新生代 标记-复制 吞吐量优先
CMS 老年代 标记-清除 并发低延迟,有碎片
G1 全堆 标记-整理+复制 区域化分代,可预测停顿
ZGC 全堆 着色指针+读屏障 超低延迟(<10ms)

六、常见误区

  1. System.gc()只是建议GC,不会立即执行
  2. 新生代GC快是因为存活对象少,不是算法本身快
  3. 标记-整理不总是更好:碎片少时标记-清除STW更短
相关文章
|
4月前
|
缓存 Java 数据库
【Spring Boot】Spring Boot 全体系知识结构化拆解(附 Spring Boot 高频面试八股文精简版)
Spring Boot 是 Pivotal 基于 Spring 的“约定大于配置”快速开发框架,简化初始搭建与开发,无缝整合 Spring 全生态,内嵌容器、自动配置、起步依赖开箱即用,是 Java 企业级应用与微服务架构的核心基石。
1525 8
|
28天前
|
存储 算法 Java
【JVM虚拟机】JVM内存结构(JDK8+):方法区、堆、虚拟机栈、本地方法栈、程序计数器,各区域作用与OOM场景(附《思维导图》+《面试高频考点清单》)
本文是面向Java开发者与面试者的JDK8+ JVM内存结构权威指南,系统梳理程序计数器、虚拟机栈、本地方法栈、堆(含年轻代/老年代/TLAB)、元空间五大运行时数据区,涵盖线程私有/共享特性、OOM场景、核心参数及高频面试题,图文结合、深度实用。
|
28天前
|
算法 Oracle Java
【JVM虚拟机】垃圾回收GC:垃圾收集器:CMS:核心原理、回收流程、优缺点、废弃原因(附《思维导图》+《面试高频考点清单》)
CMS是JDK 1.5推出的首个并发低延迟GC,专注老年代回收,以“最短STW”为目标,适用于Web交互系统。其采用三色标记+增量更新实现并发标记与清除,虽停顿短但存在CPU占用高、内存碎片、并发模式失败等固有缺陷,终被G1取代。
|
28天前
|
存储 算法 Java
【JVM虚拟机】垃圾回收GC:垃圾收集器:ZGC/Shenandoah:核心原理、低延迟特性、JDK21分代ZGC优化(2026超高频)(附《思维导图》+《面试高频考点清单》)
本文系统梳理ZGC与Shenandoah两大低延迟GC器的核心原理(着色指针/ Brooks指针、读屏障)、分代优化(JDK21+)、性能对比及调优实践,覆盖2026年面试超高频考点,助力秒答原理、设计与选型问题。
|
Java 数据安全/隐私保护 Sentinel
面试官:Sentinel是如何实现限流的?
面试官:Sentinel是如何实现限流的?
2442 1
|
28天前
|
存储 缓存 监控
【JVM虚拟机】堆内存分代模型:年轻代(Eden+Survivor)、老年代、元空间Metaspace(附《思维导图》+《面试高频考点清单》)
本文系统梳理JVM堆内存分代模型:基于弱分代假说,划分为年轻代(Eden+2×Survivor,8:1:1)和老年代(2:1),辅以元空间;详解Minor GC复制机制、对象年龄晋升、四大入老年代路径及Full GC触发条件,涵盖核心参数与调优要点。
|
28天前
|
存储 安全 Java
【Java基础】集合框架: HashMap核心原理:JDK1.7 vs 1.8+ 区别、数据结构、哈希函数、扩容机制、put/get全流程、红黑树转换阈值(附《思维导图》+《面试高频考点清单》)
本文系统对比JDK1.7与1.8+中HashMap的底层原理,涵盖数据结构(数组+链表→+红黑树)、哈希函数、扩容机制、插入方式及并发问题等核心差异,助你深入理解性能优化逻辑与面试高频考点。
|
28天前
|
存储 算法 Java
【JVM虚拟机】垃圾回收GC:垃圾收集器:G1:Region分区、Mixed GC、回收流程、适用场景(高频)(附《思维导图》+《面试高频考点清单》)
G1是JDK 9起默认的低延迟垃圾收集器,将堆划分为2048个可动态分配角色的Region,通过Mixed GC优先回收垃圾最多的区域,结合Remembered Set与SATB算法,在大堆(≥4GB)场景下实现可预测停顿(如≤200ms)与高吞吐平衡。
|
9月前
|
存储 缓存 NoSQL
Redis常见面试题全解析
Redis面试高频考点全解析:从过期删除、内存淘汰策略,到缓存雪崩、击穿、穿透及BigKey问题,深入原理与实战解决方案,助你轻松应对技术挑战,提升系统性能与稳定性。(238字)