垃圾回收算法有哪些,如何实现?

考查重点:可达性判定与空间回收。先从根判断可达对象,再标记清除、复制或整理空间;分别比较碎片、搬迁和额外内存成本

本题目录

参考答案

核心回答

在 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 日志。更低停顿可能需要更多并发工作或预留空间,没有适合所有负载的固定选择。

参考资料

相关面经

11 篇

虎牙

全栈开发
校招秋招一面
查看原面经 →
JVM 中的常见 GC 算法

字节跳动

后端开发工程师
一面
查看原面经 →
Java GC 有哪些基本算法?它们分别如何工作?

蚂蚁集团

面经合集
查看原面经 →
GC算法各自适用的场景?

顺丰

Java 开发工程师
秋招一面
查看原面经 →
垃圾回收机制

禅游科技

全栈开发工程师
实习一面
查看原面经 →
垃圾回收算法,实现
展开剩余 6 篇面经

快手

后端开发工程师
校招春招一面、二面、三面
查看原面经 →
了解哪些垃圾回收算法?

法大大

Java 开发工程师
实习一面
查看原面经 →
垃圾回收算法有哪些

公司未注明

后端开发工程师
查看原面经 →
4讲一下jvm的垃圾回收

四维图新

后端开发工程师(AI / Agent 方向)
查看原面经 →
java的垃圾回收机制。
为什么要进行垃圾回收。

字节跳动

后端开发工程师(AI / Agent 方向)
四面
查看原面经 →
java内存模型 垃圾回收

字节跳动

后端开发工程师
一面
查看原面经 →
JVM 常见的垃圾回收算法有哪些?
追问
标记清除、标记整理和复制算法分别有什么特点?

相关题目

4 题