昨天老粉阿强是的他还没找到工作去面了某独角兽公司的中间件团队。面试官问了一个看似基础、实则暗藏杀机的 JVM 题目“请说一下StackOverflowError和OutOfMemoryError的区别如果线上发生了 StackOverflowErrorJVM 进程会退出吗”阿强心想这不就是考单词拼写吗自信满满地回答“一个是栈溢出一个是堆溢出呗既然都是Error结尾的属于严重错误肯定会导致 JVM 崩溃重启啊”面试官听完合上简历冷冷地说“回去等通知吧。你对 Java 线程模型的理解连门都没入。”兄弟们这道题的通过率极低。很多人只知道它们“发生在哪”却不知道它们的“爆炸半径”完全不同。今天 Fox 就带大家从底层原理到业务场景彻底拆解这对“JVM 双煞”。一、 核心本质私有领地 vs 公共广场要理解它们的死法不同必须先看一眼JVM 运行时数据区。我们可以把 JVM 想象成一家大公司虚拟机栈 (Java Stack) —— 员工的工位 (线程私有)每个线程员工都有自己独立的工位。你在工位上堆满了文件栈帧深度过大只会导致你自己没法工作。关键点你的工位炸了通常不会影响隔壁同事的工位。堆内存 (Java Heap) —— 公司食堂 (线程共享)所有线程员工共用一个食堂。如果食堂被垃圾塞满了内存泄漏或者饭菜被吃光了内存不足。关键点所有人包括想新进来的员工都没饭吃整个公司瘫痪。二、 StackOverflowError单兵阵亡Thread Down1. 发生原因全称java.lang.StackOverflowError。它发生在虚拟机栈。当线程请求的栈深度超过了 JVM 允许的最大深度默认 1MB 左右由-Xss控制时抛出。2. 经典业务场景死递归最常见的场景就是没有出口的递归调用。场景复现你写了一个“查询父子级分类”的方法结果逻辑写歪了A 调用 BB 又调用 A。// ❌ 错误代码示范public void recursiveCall() {// 忘记写终止条件或者条件永远无法满足recursiveCall();}3. 爆炸半径重点面试官问JVM 会挂吗答通常不会现象如果你在 Web 服务如 Tomcat的一个 HTTP 线程里触发了死递归。当前线程的栈空间瞬间被打爆抛出StackOverflowError。Tomcat 主线程池捕获到这个Error注意Tomcat 会捕获 Throwable打印错误日志并向前端返回 500 错误。该线程结束销毁栈空间释放。结局那个倒霉的用户看到了报错。但是隔壁线程的栈是空的其他用户的请求依然可以正常处理。结论这是一个线程级的灾难不是进程级的。三、 OutOfMemoryError粮仓耗尽System Down1. 发生原因全称java.lang.OutOfMemoryError(OOM)。绝大多数情况发生在堆内存 (Heap)。当 JVM 无法为新对象分配内存且 GC 回收后依然不够时抛出。2. 经典业务场景大对象的一波流场景复现运营搞活动导出一个包含 100 万条记录的 Excel开发人员直接把所有数据ListUser加载到了内存。// ❌ 错误代码示范Listbyte[] list new ArrayList();while (true) {// 疯狂占用堆内存list.add(new byte[1024 * 1024]);}3. 爆炸半径重点面试官问JVM 会挂吗答虽然进程不一定立马消失但系统已经实质性瘫痪了现象那个导出 Excel 的线程把堆内存 (Heap)占满了。GC 开始疯狂工作Stop The WorldCPU 飙升 100%试图回收垃圾但回收不掉。此时正常的登录请求进来了需要创建一个小小的LoginDTO对象。JVM 说“对不起公共食堂没饭了。” -正常请求也抛出 OOM更可怕的是甚至连后台的心跳线程、日志线程都申请不到内存。结局整个应用进入“假死”状态所有接口响应超时或报错。通常我们会配置-XX:ExitOnOutOfMemoryError让 JVM 自动自杀重启否则它就是个“植物人”。结论这是一个进程级的灾难。四、 总结一张表建议打印贴工位下次面试直接把这张表甩在面试官面前维度StackOverflowError (SOE)OutOfMemoryError (OOM)内存区域虚拟机栈 (Stack)堆 (Heap) / 元空间 / 堆外资源性质线程私有(Thread Local)进程共享(Shared)触发原因方法调用太深 (死递归)内存泄漏 或 巨型对象JVM 状态存活。仅当前线程挂掉。瘫痪。全站不可用。能否恢复能。该线程释放后其他线程无影响。难。通常需要重启。排查参数-Xss(调整栈大小)-Xmx/-Xms(调整堆大小)五、 Fox 的“防杠”指南进阶必看面试官可能会追问“有没有特殊情况StackOverflowError 也会导致 OOM”Fox 满分回答“有但不是因为递归深度。如果在创建线程时无法申请到足够的栈内存比如系统总内存耗尽或者-Xss设置得太大导致每个线程都巨占内存JVM 会抛出OutOfMemoryError: unable to create new native thread。这时候虽然是栈的问题但表现出来的是 OOM这属于操作系统级别的资源耗尽。”写在最后StackOverflowError就像是你卧室的垃圾桶满了你扔不进去了但不影响你爸妈在客厅看电视。OutOfMemoryError就像是家里的冰箱空了全家人所有线程都得饿死。搞清楚“私有”和“共享”的区别你就掌握了 JVM 事故排查的钥匙。觉得讲得透彻的兄弟点个赞转发给那个以为 Error 就会宕机的同事
面试官:StackOverflowError 会导致 JVM 宕机吗?90%的人答错!
发布时间:2026/6/26 1:46:22
昨天老粉阿强是的他还没找到工作去面了某独角兽公司的中间件团队。面试官问了一个看似基础、实则暗藏杀机的 JVM 题目“请说一下StackOverflowError和OutOfMemoryError的区别如果线上发生了 StackOverflowErrorJVM 进程会退出吗”阿强心想这不就是考单词拼写吗自信满满地回答“一个是栈溢出一个是堆溢出呗既然都是Error结尾的属于严重错误肯定会导致 JVM 崩溃重启啊”面试官听完合上简历冷冷地说“回去等通知吧。你对 Java 线程模型的理解连门都没入。”兄弟们这道题的通过率极低。很多人只知道它们“发生在哪”却不知道它们的“爆炸半径”完全不同。今天 Fox 就带大家从底层原理到业务场景彻底拆解这对“JVM 双煞”。一、 核心本质私有领地 vs 公共广场要理解它们的死法不同必须先看一眼JVM 运行时数据区。我们可以把 JVM 想象成一家大公司虚拟机栈 (Java Stack) —— 员工的工位 (线程私有)每个线程员工都有自己独立的工位。你在工位上堆满了文件栈帧深度过大只会导致你自己没法工作。关键点你的工位炸了通常不会影响隔壁同事的工位。堆内存 (Java Heap) —— 公司食堂 (线程共享)所有线程员工共用一个食堂。如果食堂被垃圾塞满了内存泄漏或者饭菜被吃光了内存不足。关键点所有人包括想新进来的员工都没饭吃整个公司瘫痪。二、 StackOverflowError单兵阵亡Thread Down1. 发生原因全称java.lang.StackOverflowError。它发生在虚拟机栈。当线程请求的栈深度超过了 JVM 允许的最大深度默认 1MB 左右由-Xss控制时抛出。2. 经典业务场景死递归最常见的场景就是没有出口的递归调用。场景复现你写了一个“查询父子级分类”的方法结果逻辑写歪了A 调用 BB 又调用 A。// ❌ 错误代码示范public void recursiveCall() {// 忘记写终止条件或者条件永远无法满足recursiveCall();}3. 爆炸半径重点面试官问JVM 会挂吗答通常不会现象如果你在 Web 服务如 Tomcat的一个 HTTP 线程里触发了死递归。当前线程的栈空间瞬间被打爆抛出StackOverflowError。Tomcat 主线程池捕获到这个Error注意Tomcat 会捕获 Throwable打印错误日志并向前端返回 500 错误。该线程结束销毁栈空间释放。结局那个倒霉的用户看到了报错。但是隔壁线程的栈是空的其他用户的请求依然可以正常处理。结论这是一个线程级的灾难不是进程级的。三、 OutOfMemoryError粮仓耗尽System Down1. 发生原因全称java.lang.OutOfMemoryError(OOM)。绝大多数情况发生在堆内存 (Heap)。当 JVM 无法为新对象分配内存且 GC 回收后依然不够时抛出。2. 经典业务场景大对象的一波流场景复现运营搞活动导出一个包含 100 万条记录的 Excel开发人员直接把所有数据ListUser加载到了内存。// ❌ 错误代码示范Listbyte[] list new ArrayList();while (true) {// 疯狂占用堆内存list.add(new byte[1024 * 1024]);}3. 爆炸半径重点面试官问JVM 会挂吗答虽然进程不一定立马消失但系统已经实质性瘫痪了现象那个导出 Excel 的线程把堆内存 (Heap)占满了。GC 开始疯狂工作Stop The WorldCPU 飙升 100%试图回收垃圾但回收不掉。此时正常的登录请求进来了需要创建一个小小的LoginDTO对象。JVM 说“对不起公共食堂没饭了。” -正常请求也抛出 OOM更可怕的是甚至连后台的心跳线程、日志线程都申请不到内存。结局整个应用进入“假死”状态所有接口响应超时或报错。通常我们会配置-XX:ExitOnOutOfMemoryError让 JVM 自动自杀重启否则它就是个“植物人”。结论这是一个进程级的灾难。四、 总结一张表建议打印贴工位下次面试直接把这张表甩在面试官面前维度StackOverflowError (SOE)OutOfMemoryError (OOM)内存区域虚拟机栈 (Stack)堆 (Heap) / 元空间 / 堆外资源性质线程私有(Thread Local)进程共享(Shared)触发原因方法调用太深 (死递归)内存泄漏 或 巨型对象JVM 状态存活。仅当前线程挂掉。瘫痪。全站不可用。能否恢复能。该线程释放后其他线程无影响。难。通常需要重启。排查参数-Xss(调整栈大小)-Xmx/-Xms(调整堆大小)五、 Fox 的“防杠”指南进阶必看面试官可能会追问“有没有特殊情况StackOverflowError 也会导致 OOM”Fox 满分回答“有但不是因为递归深度。如果在创建线程时无法申请到足够的栈内存比如系统总内存耗尽或者-Xss设置得太大导致每个线程都巨占内存JVM 会抛出OutOfMemoryError: unable to create new native thread。这时候虽然是栈的问题但表现出来的是 OOM这属于操作系统级别的资源耗尽。”写在最后StackOverflowError就像是你卧室的垃圾桶满了你扔不进去了但不影响你爸妈在客厅看电视。OutOfMemoryError就像是家里的冰箱空了全家人所有线程都得饿死。搞清楚“私有”和“共享”的区别你就掌握了 JVM 事故排查的钥匙。觉得讲得透彻的兄弟点个赞转发给那个以为 Error 就会宕机的同事