前言:今日通过问答的形式讲解一下JVM内存回收的相关知识点
Q1:Java中的young gc,old gc,full gc和mixed gc的区别是什么?
A1:
| GC 类型 | 回收区域 | STW 停顿 | 典型触发条件 | 主流收集器支持 | 关键特征 |
|---|---|---|---|---|---|
| Young GC (Minor GC) | 仅新生代(Eden + Survivor) | ✅(短) | Eden 区满 | 所有分代收集器(Serial/Parallel/CMS/G1) | 高频、停顿短(ms级),复制算法 |
| Old GC | 仅老年代 | ⚠️依收集器 | 老年代空间不足(特定场景) | 极少独立存在(见下文详解) | 术语模糊:CMS 无独立 Old GC 事件;Serial Old/Parallel Old 通常作为 Full GC 的一部分 |
| Mixed GC | 新生代 + 部分老年代 Region | ✅(可控) | G1 完成并发标记后,老年代占用 ≥ IHOP(默认45%) | G1 专属 | CSet 动态选择"回收价值高"的老年代 Region,平衡停顿与回收效率 |
| Full GC | 全堆(新生代+老年代)+ 方法区(元空间) | ✅(长) | 多种(见下文) | 所有收集器(但 ZGC/Shenandoah 停顿极短) | 应用暂停时间长(百 ms~秒级),需重点监控与避免 |
深度解析与关键澄清
🔹 Young GC(Minor GC)
- 过程:清空 Eden + From Survivor,存活对象复制到 To Survivor(或晋升老年代)。
- 触发时机 :Eden区域满了就开始进行GC
- 频率:最高(秒级/分钟级),属正常现象。
🔹 Old GC
触发时机:老年代空间不足时触发

🔹 Mixed GC(G1 专属)
- 触发条件 :
InitiatingHeapOccupancyPercent(IHOP,默认45%)→ 完成并发标记 → 后续 Young GC 转为 Mixed GC。 - CSet 构成 :
所有年轻代 Region + 按"回收价值"排序的老年代 Region(垃圾比例高、回收收益大)。 - 目的 :在用户设定的最大停顿时间(
-XX:MaxGCPauseMillis)内,渐进清理老年代,避免 Full GC。 - 日志特征 :
[GC pause (G1 Evacuation Pause) (mixed), 0.025s]
🔹 Full GC ------ 高危事件!
-
核心触发条件 (需重点规避):
触发场景 说明 老年代空间不足 晋升失败、大对象分配失败 元空间(Metaspace)耗尽 -XX:MaxMetaspaceSize设置过小显式调用 System.gc()且未设置 -XX:+DisableExplicitGC担保失败 Young GC 前,老年代剩余空间 < Eden+Survivor 所有对象大小 CMS 并发失败 Concurrent Mode Failure→ 退化为 Serial Old Full GCG1 混合回收失败 to-space exhausted→ Evacuation Failure -
full gc当老年代空间不足或者元空间不足;还有调用system.gc建议敏发ful gc,但是不一定执行。会回收老年代和新生代。
-
影响:长时间 STW,服务卡顿,TPS 骤降。
收集器视角对比(关键差异)
| 收集器 | Young GC | Mixed GC | Full GC 触发特点 | 备注 |
|---|---|---|---|---|
| Serial / Parallel | 有 | ❌ 无 | 老年代回收 = Full GC(Serial Old/Parallel Old) | Parallel Scavenge + Parallel Old 组合中,老年代回收即 Full GC |
| CMS | 有(ParNew) | ❌ 无 | Concurrent Mode Failure 时退化为 Serial Old Full GC | CMS 本身无 Full GC,但失败后代价极高 |
| G1 | 有 | ✅ 有 | Mixed GC 失败(Evacuation Failure)或元空间不足 | Mixed GC 是 G1 避免 Full GC 的核心机制 |
| ZGC / Shenandoah | 无(逻辑分代可选) | ❌ 无 | 有(但停顿 < 10ms),日志称 "Pause Mark Start" 等 | 不分代设计,传统术语不适用;追求"无感 GC" |
💡 重要提示:
- "Major GC" 是模糊术语 :部分资料指 Old GC,部分指 Full GC。强烈建议避免使用,改用具体事件名(如 "CMS Remark"、"G1 Mixed GC")。
- ZGC/Shenandoah:虽有"全堆回收"动作,但因并发标记/转移,停顿极短,日志中不称 "Full GC",需结合具体收集器文档理解。
Q2:Java中常见的垃圾回收器有哪些?
A2:
| 收集器 | 定位 | 核心优势 | 适用人群 |
|---|---|---|---|
| Serial | 简单 | 无开销 | 嵌入式/学习 |
| Parallel | 吞吐 | 高吞吐 | 后台计算 |
| CMS | 低延迟 | 停顿短 | 已废弃 |
| G1 | 平衡 | 可预测停顿 | 大多数服务端应用 |
| ZGC | 极致低延迟 | <10ms | 金融/实时系统 |
| Shenandoah | 极致低延迟 | <10ms | ZGC 替代方案 |
| Epsilon | 无 GC | 零开销 | 测试/短生命周期 |
Q3:G1回收器的垃圾回收流程是怎么样子的?
A3:
下图来自https://www.mianshiya.com/

h存放超过region区域一半的大对象
G1(Garbage-First,垃圾优先)垃圾回收器的回收流程主要分为以下几个阶段:
1. 初始标记(Initial Mark):
- 暂停所有应用线程(STW)。
- 标记 GC Roots 能直接关联到的对象,速度快。
- 修改 TAMS(Next Top at Mark Start)的值。
2. 并发标记(Concurrent Marking):
- 与应用程序线程并发执行。
- 从 GC Roots 遍历对象图,标记存活对象,处理并发操作对标记的影响。
3. 最终标记(Final Mark):
- 暂停应用线程(STW)。
- 处理并发标记阶段的 SATB(Snapshot At The Beginning)记录,保证标记完整性。
4. 筛选回收(Live Data Counting and Evacuation):
- 暂停应用线程(STW)。
- 统计 Region 中存活和可回收对象信息。
- 按回收收益排序 Region,优先回收收益高的,复制存活对象到其他 Region,释放被回收 Region 空间。
G1 垃圾回收器通过分阶段回收,减少对应用程序的影响,提升内存回收效率,尤其适合大堆内存管理。
以下是对上面出现的名词的解释:
1.GC Roots 是什么?
在 Java 垃圾回收机制中,GC Roots 是一组必须活跃的引用,是垃圾回收器在标记存活对象时的起始点集合。也就是说,从这些 GC Roots 开始遍历,能直接或间接访问到的对象都被认为是存活的对象,不会被垃圾回收器回收;而那些无法从 GC Roots 访问到的对象,则被判定为可回收的垃圾对象。
常见的 GC Roots 包括以下几类:
- 虚拟机栈(栈帧中的本地变量表)中的引用:每个 Java 线程都有一个虚拟机栈,栈帧中包含局部变量表。局部变量表中引用的对象,比如方法中的参数、局部变量等所指向的对象,都是存活对象,因为只要线程还在执行相关方法,这些对象就可能会被使用,所以它们属于 GC Roots。
- 方法区中类静态属性引用的对象 :在 Java 的方法区中存储着类的静态变量等信息。如果一个类的静态属性引用了某个对象,那么这个对象也是存活的。比如一个类有一个静态的
List,这个List中引用的对象都不会被回收。 - 方法区中常量引用的对象 :方法区中的常量,如
final修饰的基本数据类型常量和对象引用常量。被这些常量引用的对象同样被视为存活对象。 - 本地方法栈中 JNI(Java Native Interface)引用的对象:当 Java 代码通过 JNI 调用本地(Native)方法时,本地方法栈中会保存一些引用,这些引用指向的对象也是存活的,会被当作 GC Roots。
【注:JNI(Java Native Interface)是Java 本地接口,是一种允许 Java 代码与其他编程语言(如 C、C++)编写的代码进行交互的技术,因为如文件系统操作等底层是 C、C++ 等语言编写的。】
2.TAMS(Next Top at Mark Start,标记开始时的下一个顶部位置)是什么?
- TAMS 是一个地址标记:在每个 Region(G1 垃圾回收器将堆内存划分为多个大小相等的 Region(块))中,都有一个 TAMS 指针。当并发标记开始时,会记录下此时 Region 中的一个地址,这个地址就是 TAMS。
- 划分对象创建时间:TAMS 将 Region 中的对象划分为两部分。在并发标记开始之前创建的对象位于 TAMS 指针之前;而在并发标记过程中创建的新对象会被分配到 TAMS 指针之后的空间。
- 而所谓的 "修改 TAMS 的值",其实是在初始标记阶段,会将 TAMS 指针设置到当前 Region 中对象分配的最新位置。
【注:"TAMS 指针前" 指的是在每个 Region 内,相对于 TAMS 指针位置而言,地址小于 TAMS 指针所指向地址的那部分内存空间。】
【注:对于 TAMS 之后的新对象,会隐式地认为是存活对象,不需要在并发标记阶段进行额外标记,简化了并发标记流程。】
【注:并发标记:在 G1 垃圾回收器的并发标记阶段,存在着垃圾回收线程与应用程序线程同时运行的状态,这种同时运行的状态即被称为并发过程。】
3.什么是对象图?
在 Java 程序运行时,众多对象被创建并存储于堆内存中,这些对象之间会通过引用彼此关联。对象图就是把这些对象当作节点,对象间的引用当作边,从而构成的一个有向图。
垃圾回收器借助从 GC Roots 开始遍历对象图,能够找出所有存活的对象。从 GC Roots 出发,沿着对象图中的引用关系不断访问其他对象,所有能够被访问到的对象都被判定为存活对象;而那些无法从 GC Roots 访问到的对象则被视为垃圾对象,可被垃圾回收器回收。
4.什么是"处理并发操作对标记的影响"?
在垃圾回收的并发标记阶段,"处理并发操作对标记的影响" 是指应对应用程序与垃圾回收线程同时运行致对象状态变化(创建、销毁、引用变更等),所采取的保标记准确措施:
- 对象创建:如 G1 中 TAMS 机制,将并发标记时新对象置于 TAMS 指针后,隐式视其存活,免复杂标记。
- 对象销毁:用 SATB 技术,初始快照结合写屏障记录引用删除,最终标记时调整结果,确可回收对象被识别。
- 引用关系变更:靠写屏障记变更,标记时综合考量,准确遍历对象图,防存活对象漏判误判。
- 数据竞争和一致性问题:在并发垃圾回收时,应用程序线程和垃圾回收线程可能同时访问和操作对象。例如,当垃圾回收器正在标记一个对象是否存活时,应用程序线程可能试图修改该对象的引用关系。通过锁机制,如互斥锁,可以确保在同一时刻只有一个线程能够访问和修改对象,避免数据竞争和不一致的情况发生,保证垃圾回收过程中对象状态的准确性,使得标记结果可靠,避免误判对象的存活状态。
通过这些方式,垃圾回收器能准确标记存活对象,为后续回收奠基。
5.什么是SATB(Snapshot At The Beginning,初始快照)?
- 初始快照概念:SATB 即 "初始快照",它的核心思想是在垃圾回收的并发标记阶段开始时,对堆内存中的对象引用关系拍摄一个快照。在这个快照中记录下了当时对象之间的引用情况,后续的标记操作主要基于这个初始的快照来进行。
- 记录引用变化:在并发标记过程中,应用程序线程持续运行,会不断创建新对象、修改对象间的引用关系或者删除引用。SATB 记录就是用来记录这些在并发阶段发生的对象引用变化的。通常借助写屏障(Write Barrier)技术来实现,当对象的引用关系被修改时,写屏障会记录下相关的信息,这些信息就构成了 SATB 记录。
- 处理 SATB 记录原因如下:一是避免对象漏标记,防止因并发时引用关系变化,使存活对象未被标记而遭误回收致程序出错。二是维护标记一致性,将并发阶段引用变化纳入标记,准确反映对象真实存活状态。三是提升并发标记效率,使垃圾回收器在并发阶段持续工作,于最终标记阶段统一处理记录,避免频繁同步开销,保证标记正确。
- 与TAMS 的协作关系:TAMS 主要负责对新创建对象的处理,从内存空间分配的角度辅助标记;而 SATB 侧重于记录对象引用关系的变化,从对象引用的角度保证标记的准确性。两者相互配合,使得 G1 垃圾回收器在并发环境下能够高效、准确地完成标记存活对象的任务。
【注:虽然并发标记阶段已经处理了部分并发操作对标记的影响,但最终标记阶段仍然需要处理 SATB 记录,因为并发标记阶段的处理难以实时跟踪全部变化,以及写屏障记录的延迟处理。】
【注:难以实时跟踪全部变化:虽然并发标记会尽力处理这些变化,但由于应用程序线程和垃圾回收线程同时运行,使得对象引用关系的变化十分频繁,很难实时且全面地跟踪所有对象引用关系的改变。例如,在极短的时间内,可能会有大量对象的引用关系被修改,并发标记过程中可能无法及时捕捉到所有这些变化。】
【注:写屏障记录的延迟处理:为了记录对象引用关系的变化,并发标记通常会使用写屏障技术。然而,写屏障只是记录下这些变化,并不会立即对标记结果进行更新。这些记录需要在后续阶段进行统一处理,以确保标记的准确性。】
6. 在 G1 垃圾回收器中,按回收收益排序 Region 的 "收益" 主要有:
- 可回收空间大小:即 Region 内垃圾对象占用空间。可回收空间大的 Region 能释放更多内存,减少碎片,回收收益高。
- 回收成本:指回收 Region 时消耗的时间和资源。存活对象少的 Region 回收成本低,收益更高。
- 对应用程序性能的影响:垃圾回收需暂停应用线程(STW),STW 时间短、对应用性能影响小的 Region 回收收益高。
G1 综合以上因素,优先回收可回收空间大、成本低且对应用性能影响小的 Region,提升垃圾回收效率与整体性能。