一个 Java 服务启动后占 500MB,跑 12 小时涨到 3GB 然后被 OOM Killer 杀掉,重启后重复这个过程。请说:你怎么判断这是内存泄漏而不是缓存或正常增长?要拿证据你会用哪些命令/工具?操作时要注意什么风险?
面试官在考什么
是否理解内存泄漏的判断依据,知不知道怎么拿证据以及取证动作本身的代价。
回答框架 · 前两步
- 先看趋势与相关性:内存随运行时长/请求量单调上涨、Full GC 后老年代回收不下来、重启就恢复,才更像泄漏;缓存预热、连接池扩容、大对象常驻要排除。
- 分层看是谁在涨:RSS 涨不等于堆涨,还要看堆、Metaspace、直接内存、线程栈、本地库。
还有 3 条答案要点、 3 层追问、 5 个常见坑, 以及针对你简历的追问路径,在定制报告里。
同一能力域的其他题
- 生产环境某接口每天偶发几笔“参数校验失败”,现有日志只有一行“invalid param”,没有请求上下文,也无法在测试环境复现。约束:不能重启服务、不能停流量、不能改业务逻辑。你如何在不影响线上稳定的前提下补日志或使用断点定位?请给出操作顺序、日志字段和级别、断点使用条件,以及日志量过大时的控制手段。
- 线上一个服务 QPS 约 5000,某核心接口 P99 约 200ms。存在一个约万分之一概率的数据不一致问题,平均每天出现 3~5 次,本地和压测环境都复现不出来,下一次上线窗口在一周后。现在要在生产现场抓这个问题的证据。请具体说明:你会用日志还是断点(或动态追踪)?日志打在哪一层、打哪些字段、如何控制采样?如果在 5000 QPS 的进程上挂一个阻塞式断点,会造成什么后果,你用什么手段规避?
- 你们的在线推理服务跑在 60 个 Pod 上,高峰 8k QPS,每个请求平均打 12 行 INFO 日志,日志平台按写入量计费。现在日增 30TB、保留 30 天,日志成本已经接近计算成本的一半,但 SRE 依然抱怨出事时日志不够用。请给出你的日志治理方案:分级和采样怎么定、哪些日志必须 100% 保留、如何在量降下来的同时不丢排查能力,以及你打算怎么推动各业务方配合。另外说清楚:生产环境需要看某个 Pod 的详细执行过程时,你会用断点还是动态日志,为什么。
- 一个 Flask 接口线上每天有几次返回 500,日志里只有一行 "handle request failed",没有堆栈;本地用同样的参数打了几千次都复现不了。请说出你接下来会怎么改日志让下一次失败能自证原因:加哪些字段、用什么级别?另外有人提议直接在线上挂断点单步调试,你怎么看?
- 某接口 P99 从 200ms 涨到 1.2s,平均耗时只涨了约 100ms,CPU 使用率没有明显变化,入口 QPS 基本不变。你手上只有该服务的性能剖析工具(CPU profiler、锁分析、GC 日志、链路追踪)和少量机器权限。请说明你会先看什么、再看什么,如何逐步区分是 CPU、锁、GC、IO、下游依赖还是排队导致的长尾。
- 线上服务 QPS 稳定在 2000,业务量没有变化,但接口 P99 从 50ms 恶化到 300ms。机器 CPU 使用率只有 60%,内存指标正常,下游依赖的 RT 监控也没变化。团队第一反应是“扩容加副本”。请说明你的排查路径:你会先看哪些指标,选择哪种 profiling(CPU sampling、wall-clock、off-CPU、锁/GC/IO 等待分析),为什么?在这个场景下扩容能不能解决问题?