垃圾回收算法有哪些,如何实现?
未标记
考查重点:可达性判定与空间回收。先从根判断可达对象,再标记清除、复制或整理空间;分别比较碎片、搬迁和额外内存成本
本题目录
参考答案
核心回答
在 Java 面试语境下,常见的垃圾回收算法有标记—清除、复制和标记—整理。回答时先分两步:先判断哪些对象需要保留,再决定怎样回收空间。分代收集是在对象寿命不同的前提下组织回收的策略,G1 等垃圾收集器则是这些机制的具体实现。
判断对象存活时,HotSpot 主要采用可达性分析:从线程栈、JNI 等位置持有的 GC Roots 引用出发,沿引用关系遍历,找出仍然可达的对象。两个对象即使互相引用,只要整体已经无法从根到达,也可以被回收;单纯的引用计数则难以独立处理这种循环引用。这里讨论普通对象的强可达性,软、弱引用等还有各自的处理规则。
三种算法分别通过清理死亡对象留下的空闲块、复制存活对象到目标区域、移动整理存活对象来回收空间。取舍主要在碎片、预留空间与对象搬迁成本;分代和并发机制可以与它们组合,具体策略由收集器和负载决定。
三种回收算法怎样实现
三种回收算法的主要区别是:
- 标记—清除:先标记存活对象,再扫描待回收区域,把未标记对象占用的空间交还给分配器,例如加入空闲块管理结构。它不搬动存活对象,但空闲空间可能散落在多个位置,出现“总空闲空间够,连续空间不够”的碎片问题。清除不等于逐字节把内存写成零,也不等于立即归还给操作系统。
- 复制:把存活对象搬到另一片空间,修正指向这些对象的引用,然后整体回收原空间。复制过程中需要记录对象的新位置,避免同一个对象被重复复制。回收后的空间较规整,对存活对象少的区域很合适;代价是需要目标空间,而且存活对象越多,搬迁工作通常越多。经典的半区复制会预留另一半空间,但不能据此说所有采用复制的收集器都只能使用一半堆。
- 标记—整理:先标记存活对象,再确定新位置、搬迁对象并修正引用,使存活对象集中,释放整理后的空闲空间。它能减少碎片,也不要求像经典半区复制那样预留等大的另一半空间,但需要付出地址计算、对象移动和引用调整的成本,具体过程取决于实现。
例如,假设一个待回收区域中大部分对象都已死亡,复制少量存活对象就能整体释放原区域;如果区域中大部分对象都还活着,搬迁成本就可能很高。算法的成本要结合存活对象、引用关系和空间布局判断,不能简单排一个永远适用的效率顺序。
分代收集如何组合这些算法
分代收集利用的是“很多对象很快死亡,部分对象会存活很久”的经验规律。常见做法是更频繁地回收年轻对象,存活较久的对象再晋升到老年代,减少每次都处理整个堆的工作。
经典年轻代回收中,Eden 和一个 Survivor 区的存活对象可以复制到另一个 Survivor 区,必要时晋升老年代,随后交换 Survivor 的角色。实际晋升受年龄、目标空间和收集器策略等因素影响,不能说所有对象都固定经过 15 次回收。
只回收年轻代时,还必须处理老年代指向年轻代的引用,否则可能误回收仍被使用的对象。收集器会借助写屏障、卡表或记忆集等机制记录相关信息,避免每次都完整扫描老年代。这里的写屏障是 GC 跟踪引用变化的机制。
老年代也并非只能采用清除或整理。例如,以 JDK 25 的 G1 为例,它将堆划分为 Region,先获取存活信息,再在回收暂停中把选定 Region 的存活对象疏散到其他 Region,修正引用并释放原区域;Mixed GC 还会包含部分老年代 Region。这说明“分代”与“复制”可以组合,不能把年轻代、老年代和某一种算法永久绑定。
并发回收为什么还需要停顿
并发标记期间,应用也在改变对象引用,收集器必须保证不会漏掉仍然存活的对象。G1 使用 SATB 等机制维护标记正确性,并在部分阶段暂停应用线程完成必要工作。
因此,并发 GC 不等于全程没有停顿,STW 也不等于只用一个 GC 线程。以 G1 为例,并发标记、并行疏散和短暂停顿会一起工作,停顿目标是尽力满足的目标,不能当作每次回收的硬保证。
常见追问
有垃圾回收,为什么还会内存泄漏?
GC 判断的是对象是否仍然可达,不知道业务是否还需要它。长期存活的集合、缓存或线程上下文如果一直持有不再需要的对象,这些对象仍然可达,GC 就不能随意清除。处理时要找到并解除不必要的引用,而不是只增加回收频率。
实际项目怎么选择?
通常选择和调优的是收集器,而不是自己指定某一步使用清除还是复制。要先确认 JDK 版本和实际收集器,再结合分配速率、存活数据量、堆与 CPU 预算,以及吞吐量和尾延迟目标观察 GC 日志。更低停顿可能需要更多并发工作或预留空间,没有适合所有负载的固定选择。
参考资料
- 国内:JavaGuide:JVM 垃圾回收详解:参考引用计数、可达性分析和三种基础算法的讲解,组织正文中对象存活判断、空间回收及分代组织的区别。
- 国内:沉默王二:深入理解 JVM 的垃圾回收机制:借鉴清除、复制和整理的过程,比较正文中的碎片、目标空间与对象搬迁、引用调整成本。
- 国内:美团小亮:Java Hotspot G1 GC 的一些关键技术:参考 SATB、写屏障和跨 Region 引用记录,解释正文中并发标记与局部回收的正确性条件;涉及版本的实现细节仍以文中限定的 G1 为例。
- 国外:Oracle JDK 25:Garbage Collector Implementation:借鉴对象可达性、寿命分布和经典 Survivor 复制的说明,解释正文中分代的经验依据及半区复制的适用范围。
- 国外:Oracle JDK 25:Garbage-First Garbage Collector:疏散、引用修正和 Mixed GC 的定义说明老年代 Region 也可以参与搬迁回收;SATB 与停顿目标部分进一步解释并发和暂停怎样配合。
相关面经
11 篇虎牙
全栈开发JVM 中的常见 GC 算法
字节跳动
后端开发工程师Java GC 有哪些基本算法?它们分别如何工作?
蚂蚁集团
GC算法各自适用的场景?
顺丰
Java 开发工程师垃圾回收机制
禅游科技
全栈开发工程师垃圾回收算法,实现




