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

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

本题目录

参考答案

核心回答

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

参考资料

相关面经

29 篇

百度

后端开发
实习二面
查看原面经 →
JVM的垃圾回收策略有哪些

启云方

AI Agent
秋招二面
查看原面经 →
问项目,项目问的时间比较长,大概问有十几分钟 最后问了一个八股问题,java的垃圾回收机制,我只回答出了一半。。

东方财富

服务端开发工程师(AI应用开发方向)
实习秋招一面、二面
查看原面经 →
JVM 垃圾回收有哪些常见算法和垃圾回收器?

虎牙

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

字节跳动

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

蚂蚁集团

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

星龙数智

Java / 大模型开发
实习
查看原面经 →
介绍标记清除、标记整理、复制这几种垃圾回收算法

高途

后端开发
校招秋招一面
查看原面经 →
JVM:运行时内存区域、线程共享/私有、栈帧结构、对象如何判断可以回收、GC 算法和垃圾收集器

百度

面经合集实习
查看原面经 →
问了一些java的八股,麻了,主要一开始想着测开,没太准备八股,结果问了jvm内存里面有哪些,回答了一个堆,栈,常量区。然后问我gc,我一开始还没反应过来。 然后是java的多线程怎么创建,就回答了一个thread和一个runable。也不知道对不对

顺丰

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

字节跳动

全栈开发
实习二面、三面
查看原面经 →
简单说说垃圾回收机制的了解

禅游科技

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

华为

Java 开发
一面、二面
查看原面经 →
垃圾回收算法

快手

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

虾皮

后端实习
实习一面
查看原面经 →
了解过虚拟机或垃圾回收机制吗?

法大大

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

公司未注明

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

美团

测试开发
一面
查看原面经 →
内存垃圾回收

蚂蚁集团

后端开发实习生
暑期实习
查看原面经 →
JDK 8 的垃圾回收算法有了解吗?

钉钉

Java 研发
暑期实习一面
查看原面经 →
jvm内存回收;什么情况下适合标记清除,什么标记整理

阿里国际

AI 应用开发
一面
查看原面经 →
可以详细讲下垃圾回收算法吗

飞猪

Java 后端开发
一面
查看原面经 →
垃圾回收算法,分别用在什么场景

字节跳动

后端开发
暑期实习一面
查看原面经 →
Java 的垃圾回收算法、特点及使用场景? //混淆算法和具体实现了 答的磕磕巴巴

龙旗科技

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

腾讯

后台开发
一面
查看原面经 →
GC回收器有哪些?说一下CMS吧,有哪些GC的方法(算法)

腾讯

后端开发
暑期实习一面
查看原面经 →
对 Java 的垃圾收集(GC)有没有了解?谈谈判断条件和回收算法。

四维图新

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

字节跳动

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

字节跳动

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

相关题目

4 题