[面试题] OOM 和 StackOverflow 的区别是什么?Java 发生 OOM 一定会导致 JVM 退出吗?
📖 版块 A:知识讲解版 (温故知新)
-
StackOverflowError:
- 通常表示线程栈空间耗尽。
- 常见原因是递归过深、方法调用层级过深、单个栈帧过大。
-
OOM(OutOfMemoryError):
- 是更广义的内存申请失败。
- 可能发生在堆、元空间、直接内存,甚至创建线程时的本地资源耗尽。
-
两者核心区别:
- StackOverflow 更偏“线程栈爆了”。
- OOM 更偏“某类内存或资源申请失败了”。
-
OOM 一定导致 JVM 退出吗:
- 不一定。
- 有些 OOM 只是当前线程抛异常,业务层如果处理得当,进程未必立刻退出。
- 但某些严重 OOM 会让进程基本失去恢复能力。
- 如果开启
-XX:+ExitOnOutOfMemoryError,则出现 OOM 时 JVM 会直接退出。
🎤 版块 B:面试实战版 (高手逐字稿)
Q:OOM 和 StackOverflow 的区别是什么?Java 发生 OOM 一定会导致 JVM 退出吗?
💬 高手逐字稿:
OOM 和 StackOverflowError 虽然都和内存有关,但本质上是两类完全不同的问题。
StackOverflowError 通常表示线程栈空间耗尽。最典型的场景就是无限递归,或者方法调用层级太深,导致栈帧一个接一个往里压,最终把线程栈打爆了。
而 OOM,也就是 OutOfMemoryError,含义要宽得多。它不只是说“堆满了”,而是说某类内存或系统资源申请失败了。常见的包括:
- Java 堆不够;
- 元空间不够;
- 直接内存不够;
- 甚至创建新线程时,本地资源耗尽。
所以两者的区别可以粗暴记成:
- SOF 是“栈太深,压爆了”;
- OOM 是“某块资源想申请但申请不到了”。
第二个问题也很重要:Java 发生 OOM 一定会导致 JVM 退出吗?
答案是不一定。有些 OOM 只是当前线程抛了一个错误,理论上如果业务代码能捕获并做兜底,进程不一定立刻退出。但从工程角度讲,很多 OOM 发生时,系统其实已经进入高风险状态了,尤其是堆、元空间或者本地内存被打满之后,后续行为会非常不稳定。
另外还有一个参数值得顺手提一下:如果配置了 -XX:+ExitOnOutOfMemoryError,那 JVM 在出现 OOM 时会更果断地直接退出。
所以最好的总结是:OOM 不一定等于 JVM 立刻死亡,但很多 OOM 场景已经意味着进程离不可恢复很近了。
最后更新于: