catch(Exception e)抓不到OutOfMemoryError,因为Exception与Error是Throwable的两个平级子类,无继承关系;OutOfMemoryError直接继承Error,不在Exception继承链上。

catch(Exception e) 为什么抓不到 OutOfMemoryError
因为 Exception 和 Error 是 Throwable 的两个**平级子类**,没有继承关系。你写 catch (Exception e),就像想用渔网捞飞机——类型根本不匹配。
-
OutOfMemoryError、StackOverflowError都直接继承自Error,不在Exception的继承链上 - 编译器允许你写
catch (Error e),但这是危险操作:此时 JVM 很可能已处于不可靠状态(比如堆内存全满、栈帧损坏) - 真正该做的是在 JVM 启动参数里加
-XX:+HeapDumpOnOutOfMemoryError,配合jstat或VisualVM定位泄漏点,而不是靠 try-catch“兜底”
什么时候必须处理,什么时候可以不写 try-catch
Java 编译器只强制你管一类异常:Checked Exception——即直接继承 Exception 但**不继承 RuntimeException 的那些,比如 IOException、SQLException。
- 不处理?编译直接报错:
Unhandled exception type IOException -
RuntimeException及其子类(如NullPointerException、ArrayIndexOutOfBoundsException)属于Unchecked Exception,编译器放行,但建议用判空、校验、防御性编程提前规避 -
Error全系都是 unchecked,编译器完全不管——但这不等于“可以放心 catch”,而是“你不该去 catch”
自定义异常该继承 Exception 还是 Error
永远选 Exception 或它的子类(比如业务异常继承 RuntimeException),**绝不能继承 Error**。
- 继承
Error会误导调用方:它暗示“这问题 JVM 都扛不住了”,但实际只是你的业务逻辑出错了 - 监控系统、APM 工具捕获
Error是为了记录 + 快速退出,不是为了恢复;你的业务代码里出现catch (Error e),基本可以判定是反模式 - 典型错误写法:
public class MyBusinessError extends Error { ... }—— 正确写法应为:public class InsufficientBalanceException extends RuntimeException { ... }
遇到 StackOverflowError,真能靠 try-catch 挽救吗
不能。一旦触发 StackOverflowError,当前线程的调用栈已损坏,后续任何方法调用(包括 System.out.println、logger.error)都可能失败。
立即学习“Java免费学习笔记(深入)”;
- 下面这段代码看似“兜住了”,实则危险:
try { recursion(); } catch (StackOverflowError e) { System.out.println("我抓住了栈溢出!"); // ❌ 可能根本执行不到这一行 } - 真实场景中,应该检查递归终止条件、改用迭代、或限制最大调用深度(如传入
depth参数并校验) - 如果日志框架本身用了递归或反射,
catch (Error)甚至可能导致死锁或静默崩溃








