StackOverflowError和OutOfMemoryError均属VirtualMachineError,反映JVM底层内存崩溃:前者因栈深度超限致无法压入新栈帧(含catch块执行),后者因关键内存区耗尽、GC失效,连创建Throwable对象都可能失败,故程序无法安全继续执行。

不能继续执行。StackOverflowError 和 OutOfMemoryError 都是 VirtualMachineError 的子类,属于严重错误(Error),不是普通异常(Exception)。JVM 设计上认为这类错误已破坏运行时基本前提,程序无法安全恢复,因此不建议捕获、更不应尝试继续执行业务逻辑。
为什么不能继续执行
这两类错误反映的是 JVM 内存结构的底层崩溃状态:
- StackOverflowError:当前线程的 Java 虚拟机栈已耗尽,连方法返回、异常处理本身所需的栈帧都可能无法压入。即使用 try-catch 包裹,catch 块的执行仍需新栈帧——此时很可能直接失败或触发二次错误。
-
OutOfMemoryError:堆、元空间或直接内存等关键区域已无可用空间。GC 已多次尝试失败,连创建一个
String或Throwable实例都可能失败。此时任何对象分配(包括日志、清理、重试)都极大概率再次抛出 OOM。
捕获后能做什么(仅限有限兜底)
若确需捕获(如顶层监控、日志记录),目标应是快速、最小化、无分配地收尾:
- 仅调用不分配对象的方法,例如
System.err.println()(注意:某些重载会隐式创建 String); - 避免日志框架(log4j、slf4j 等),因其内部常涉及对象创建和锁竞争;
- 可调用
Runtime.getRuntime().halt(1)强制终止进程(不触发 shutdown hook),比让线程随机挂起更可控; - 在 main 线程中捕获后,可尝试关闭关键资源(如已打开的文件句柄、Socket),但前提是这些操作本身不依赖新对象分配。
真正有效的应对方式
重点不在“错误发生后怎么续跑”,而在于提前预防与快速止损:
- 对递归逻辑强制设置深度上限(如传入 maxDepth 参数),改用显式栈(
Deque)实现迭代; - 堆内存问题通过
-XX:+HeapDumpOnOutOfMemoryError自动导出堆快照,配合 MAT 分析泄漏点; - 限制线程数、连接数、缓存大小等资源边界,防止雪崩式内存增长;
- 在容器或服务治理层配置内存/线程熔断(如 Kubernetes memory limit + OOMKill,或 Sentinel 限流)。


















