拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

07 这道题面试官爱问:你在生产环境选了哪个垃圾回收器,以及为什么

07 这道题面试官爱问:你在生产环境选了哪个垃圾回收器,以及为什么

去年面过一个做基础架构的,简历写着"曾负责公司 JVM 调优,将接口延迟降低 40%"。

我说:挺好。那你在生产环境用的是哪个垃圾回收器?

"G1。"

"具体为什么选 G1,而不是 CMS 或者 ZGC?"

他想了一会儿:"因为……G1 是现在的主流,兼顾了吞吐量和延迟。"

我说:"行。那我再问一句——G1 的 Mixed GC 和 Young GC 有什么区别?"

他的手掌开始出汗。

"Mixed GC 除了回收 Young 区,还回收一部分 Old 区……"

"哪一部分?"

他答不出来了。

不是因为他不够聪明,是因为 99% 的人在面试这道题时,把"知道垃圾回收器有哪些"等同于"知道怎么选垃圾回收器"。而面试官在问这题时,脑子里的画面是一个 4 核心、8GB 的服务器,上面跑着 2000 TPS 的交易系统。他的人问你这些,不是因为好奇你在简历上写的字——他是真的在给你这个场景,看你能不能做出正确判断。

讲清楚一件事——选垃圾回收器就是个三体问题

你拿垃圾回收器来优化系统,你永远要权衡三个东西:

指标含义为什么重要吞吐量程序干活的时间 /(干活 + GC 的时间)吞吐量高的系统 GC 很少暂停——吞吐量 99%,意味着只有 1% 的时间在做 GC暂停时间GC 造成的 STW (Stop-The-World) 时间暂停时间长,一个接口就卡住了。交易系统宁可吞吐量稍微低一点,也受不了单次暂停超过 200ms内存占用垃圾回收需要用的额外内存堆内存是物理资源,GC 调优的本质就是在这三个变量之间找交点

没有人能同时满足三个。你的系统是什么类型,决定了你优先满足哪个。

七个回收器,我帮你画成一条故事线

1. Serial / Serial Old —— 上古神兽,依然在用

单线程 GC。新生代用 Serial(标记-复制),老年代用 Serial Old(标记-整理)。GC 时整个应用暂停。

什么场景还在用它?微型服务、桌面应用、嵌入式设备、几百兆的堆。Java 的 Client 模式默认使用它。核心数少、堆小的情况——单线程反而没线程切换的成本。

2. Parallel / Parallel Old —— 吞吐量之王

多线程版 Serial。新生代 Parallel Scavenge,老年代 Parallel Old。同样是 Mark-Compact。它的唯一目标是吞吐量——让 CPU 花尽量少的时间做 GC。

什么场景用?批处理、数据计算、科学计算。你能容忍偶尔暂停几秒,但不能容忍 CPU 被 GC 长期占用。

3. ParNew + CMS —— 当年统治一切的老一代帝王

ParNew 是多线程版的 Serial(用于新生代)。CMS 是并发的老年代回收器——它最大的创新是:老年代 GC 和应用线程可以并发执行。CMS 分四步:初始标记(STW很短)→ 并发标记(和应用线程一同跑)→ 重新标记(STW)→ 并发清除。

那它为什么被淘汰了?三个死穴:第一,会产生内存碎片,因为没有整理(Compact)过程——碎片多了 Full GC 由 Serial Old 来收底,暂停时间直接炸锅;第二,并发标记过程中会产生浮动垃圾,等下次 CMS 才能清理;第三,底层大量用内存(CPU 资源碎片化管理)。

4. G1 —— 现在的事实标准

G1 —— Garbage First 垃圾回收器。它的创新是:把堆切成一堆等大的 Region,每次找准垃圾最多的几个 Region 优先回收。Young GC 回收 Young 区;Mixed GC 回收 Young 区 + 部分老年代的 Region。不一次回收全部老年代,把回收任务拆散到多次 Mixed GC 里——暂停时间预判可控。

-XX:MaxGCPauseMillis=200是 G1 最有代表性的参数——你告诉它"每次 GC 给我控在 200ms 以内"。G1 会尽量满足你,哪怕为此少回收几个 Region。

什么时候选 G1?

  • 堆 4GB 到 32GB 之间
  • 需要暂停时间可控
  • 6 核心以上

5. ZGC —— 新王登基

ZGC 的野心很大的:10ms 以下的暂停时间,跟堆大小几乎无关。我用它处理过 16TB 的堆——暂停时间 1.5ms。物理世界里的一个 blink。

它怎么做到的?ZGC 的核心技术是染色指针(Colored Pointers)——在 64 位指针里用几个 bit 来标记对象状态,不需要在对象头里额外加标记。再加读屏障(Read Barrier),让 GC 线程和应用线程之间的部分工作通过自愈生成指针解决。

代价呢?吞吐量比 G1 稍低(大概低 5-10%),而且只能用在大堆上才有意义。堆小于 4GB 不如用 G1。

什么时候选 ZGC?

  • JDK 11 以上
  • 对你的系统来说,一次 GC 暂停时间超过 10ms 是不可接受的
  • 你的堆是几十 GB 以上量级

面试分三档

第一档:能说出 CMS / G1 / ZGC 的名字——不及格。说明百度过。

第二档:在第一档基础上能基本说清楚 CMS 的缺点(碎片、浮动垃圾、并发失败 Full GC);能说 G1 的 Region 布局和 Mixed GC 机制;知道 ZGC 的目标暂停时间 10ms 以内——通过线。

第三档:在第二档基础上,一句定性的话:"小型应用、单核用户机,Serial 够用;批处理系统求吞吐量,Parallel 首选;Web 服务堆 4GB+ 了,CMS 换 G1;堆足够大且需要更低延迟,上 ZGC。"

面试官的脑子里会自动把这幅图补充出来:你不是在背七个名字。你把 Java 垃圾回收的设计演进线路在心里铺成了一条路。来一个场景你知道该往哪走。

选垃圾回收器这道题,你面试时是被怎么追着打的?留言区说说。

本文作者:资深 Java 开发老兵,前大厂面试官。不讲八股文,只讲面试官心里在想什么。系列持续更新,关注不迷路。

如果觉得有帮助,点个关注支持一下。

我最近整理了一份《大厂面试老兵资料包》,里面有评分表、高频场景题还有今年新出的 AIGC 面试题,

都是 200 多场面试里一点点攒的,市面上没人这么整理过。

需要的朋友私信我回复「666」,我发你领取方式。

返回列表