面试官最爱问的FullGC排查实战:从日志分析到堆转储的完整避坑指南
最近和几位准备面试的朋友聊天,发现一个挺有意思的现象:大家刷了不少JVM八股文,对垃圾回收算法、内存区域划分倒背如流,可一旦被问到“线上系统频繁FullGC,你怎么排查?”这种实战问题,回答往往就变得支支吾吾,逻辑混乱。面试官想听的,不是教科书上的理论复述,而是一套清晰、可落地、能体现你工程化思维的排查路径。这就像医生看病,光知道人体解剖结构没用,关键得会看化验单、会分析CT影像,最后能开出对症的药方。
频繁FullGC本质上是一个系统性问题的外在症状,它可能源于一行有问题的代码,也可能指向整个架构设计的缺陷。一个成熟的开发者,应该具备从监控告警的“现象感知”,到日志分析的“线索追踪”,再到堆转储深度剖析的“根因定位”,最后给出“根治方案”的完整能力闭环。这篇文章,我就结合自己踩过的坑和带团队处理线上问题的经验,为你梳理一套面试中能清晰表达、工作中能直接上手的FullGC排查实战指南。我们会从最外部的监控指标看起,一步步深入到GC日志的蛛丝马迹,最后用MAT等工具给内存做个“解剖”,让你不仅知道怎么做,更明白为什么这么做。
1. 建立观测:从系统指标到JVM内部视角
排查任何问题,第一步永远是“看见”。在FullGC问题上,盲目登录服务器敲命令是低效且危险的。一个成熟的工程师,应该首先依赖完善的监控体系来定位问题的大致范围和严重程度。这不仅能快速缩小排查范围,也能在面试中体现你具备“可观测性”的现代运维思维。
1.1 系统层与业务层监控:建立问题关联
FullGC不会孤立发生,它一定会体现在系统指标和业务指标上。面试时,你可以这样描述你的第一反应:“我会先看整体监控大盘,确认FullGC是否已经对业务造成了实质性影响,并初步判断问题的紧急程度。”
核心监控看板与指标:
-
系统资源监控:
- CPU使用率与负载:频繁的FullGC会导致GC线程长时间占用CPU,表现为系统CPU使用率,特别是
%sys或%iowait(如果GC涉及大量对象移动)异常升高,而%user(应用线程)占比下降。使用top命令查看整体情况,再用top -Hp <pid>查看具体Java进程的线程情况,如果看到多个GC task thread线程CPU消耗持续高位,这就是一个强烈信号。 - 内存使用趋势:通过
free -m或监控平台观察系统剩余内存。虽然JVM管理堆内内存,但频繁FullGC可能导致堆外内存(如Direct Buffer、Metaspace)或物理内存的异常波动,这也是一个辅助判断点。
- CPU使用率与负载:频繁的FullGC会导致GC线程长时间占用CPU,表现为系统CPU使用率,特别是
-
业务应用监控:
- 应用吞吐量与延迟:这是最直接的业务影响体现。查看QPS是否出现断崖式下跌,接口平均响应时间(Avg)、95分位(P95)、99分位(P99)响应时间是否出现周期性尖刺。如果这些尖刺与后续发现的GC时间点吻合,就建立了FullGC导致业务受损的直接证据链。
- 错误与超时率:观察是否有大量超时错误、熔断器开启或线程池满载拒绝。这些往往是FullGC导致STW时间过长,请求堆积后的连锁反应。
提示:在面试中,强调你会关联时间点。例如:“我发现每天下午2点左右,订单服务的P99延迟就会从50ms飙升至2秒,同时监控到该实例的CPU使用率出现周期性峰值。我怀疑这个时间点有定时任务或流量高峰触发了密集的垃圾回收。”
1.2 JVM内部指标:定位问题核心
在系统层指标发出警报后,我们需要深入JVM内部,获取更精确的数据。这里主要依靠JMX暴露的指标。
关键JVM监控指标(通过Prometheus + Grafana或类似平台):
| 指标类别 | 具体指标 | 正常阈值参考 | 异常信号解读 |
|---|---|---|---|
| 堆内存 | jvm_memory_used_bytes{area="heap"} |
老年代使用率应呈锯齿状,有升有降 | 老年代使用率持续走高,FullGC后释放很少(<20%),可能内存泄漏 |
jvm_memory_used_bytes{area="nonheap"} (Metaspace) |
相对稳定,缓慢增长后平台期 | 持续快速增长,可能类加载泄漏 | |
| 垃圾回收 | jvm_gc_pause_seconds_count{gc="G1 Old Generation"} (Full GC次数) |
越低越好,理想情况天级别甚至更久 | 次数频繁增加(如>1次/分钟) |
jvm_gc_pause_seconds_sum{gc="G1 Old Generation"} (Full GC总耗时) |
- | 耗时持续增长,或单次耗时过长(>1秒)</ |

518

被折叠的 条评论
为什么被折叠?



