兄弟们,说个真事。
我一个哥们上周面字节跳动,三面都过了,结果挂在二面的一道题上。对,你没看错——二面,不是三面。
面试官喝了口水,不紧不慢地抛出问题:
"凌晨两点,你负责的推荐服务突然OOM挂掉。运维重启之后,过了四十分钟又挂了。你是Owner,现在给你五分钟,告诉我怎么做。"
我那哥们一听,心想这题不简单吗?
"内存不够那就加内存啊,把-Xmx从 4G 翻到 8G。实在不行,先重启稳住,白天再慢慢查。"
面试官放下水杯,眼神变了——
"加内存?如果是 ThreadLocal 泄漏,你加到 128G 它也能给你吃干净。重启?案发现场你一个键都不留就重启?你知不知道jmap在生产环境执行一次,整个服务可能 STW 十几秒?"
一句话总结结局:凉了,当场凉了。
这道题表面考 JVM,实际考的是生产事故应急能力和内存现场分析能力。加内存是小白本能反应,但面试官要的是能独立扛事故的人,不是只会氪金的 RMB 玩家。
今天就把这道 P7 级大题拆开揉碎,别让兄弟们在同一个坑里摔两次。
一、第一层|OOM 不是一种病——先把敌人认清楚
面试时很多人张嘴就"OOM 了",但面试官心里已经在摇头了:OOM 有三种典型死法,你说的是哪一种?
1. 老年代塞满——Heap Space OOM(出场率最高)
日志里会看到:
java.lang.OutOfMemoryError: Java heap space
翻译成人话:你家的仓库满了,垃圾回收车跑了N趟还是腾不出地方。
典型作案现场:
- 某接口把几十万条数据塞进一个ArrayList做内存分页,压根没考虑流式处理
- ThreadLocal里存了用户 Session,用完从没remove()
- 本地缓存无上限地往里塞,以为对象会自动消失
2. 类装不下了——Metaspace OOM
java.lang.OutOfMemoryError: Metaspace
这不是仓库爆了,是你家的档案室(元空间)塞不下了。跑着跑着,JDK 动态代理、CGLib、Spring AOP 在运行期间悄悄生成了巨量的代理类,把装 Class 的元空间撑炸了。
3. 隐形炸弹——堆外内存溢出
日志里没有明显的OutOfMemoryError,但进程就是被系统kill -9了。这才是最坑的——Direct Buffer Memory 不归 JVM 堆管,你用 Netty 写了个ByteBuffer.allocateDirect()没释放,堆内看着一切正常,但 OS 视角下进程内存已经逼近上限了。


闽公网安备 35020602001684号