Java自定义异常必须继承Exception或RuntimeException,否则JVM字节码校验失败报VerifyError;athrow指令仅识别这两类及其子类;需提供String和Throwable双参构造函数,慎重写fillInStackTrace()。

Java自定义异常类必须继承Exception或RuntimeException
不继承这两个基类,JVM在字节码校验阶段就会拒绝加载——VerifyError: Bad type on operand stack是常见报错。编译器允许你写class MyException extends Throwable,但运行时会失败,因为JVM要求所有异常对象必须能被athrow指令识别,而该指令只接受Exception及其子类(含RuntimeException)。
实操建议:
- 业务异常用
Exception子类(强制调用方处理),比如InsufficientBalanceException - 编程错误类异常用
RuntimeException子类(如InvalidStateException),避免污染正常流程 - 务必提供带
String和Throwable参数的构造函数,否则getCause()和日志堆栈会丢失根因 - 不要重写
fillInStackTrace()除非明确需要性能优化——它跳过栈帧收集,会导致printStackTrace()输出为空
异常表(exception_table)决定catch块能否生效
Java字节码里没有try-catch语法糖,只有exception_table结构:它记录了「从哪条指令到哪条指令」范围内,「遇到哪种异常类型」时,跳转到哪条指令执行catch逻辑。这个表由编译器生成,但行为受源码中catch顺序和异常继承关系严格约束。
常见错误现象:
立即学习“Java免费学习笔记(深入)”;
Java Maven 项目审查工作流的通用输入处理。当 Java Maven 项目以 ZIP压缩包或 GitLab 仓库 URL 形式提供且需要...时使用。
-
catch (Exception e)写在catch (IOException e)前面 → 后者永远无法命中,编译器直接报错 - 自定义异常未声明在
throws列表中,却在catch里捕获 → 编译通过,但exception_table不会为它生成条目,运行时照样抛出未处理异常 - 在
finally块里return,导致catch中抛出的异常被吞掉——这不是exception_table问题,而是JVM规范强制覆盖返回值
throws声明影响的是编译期检查,不是字节码异常流
throws只是告诉编译器「这个方法可能抛出这些异常」,它不改变字节码中的exception_table,也不影响JVM运行时的异常分发路径。真正起作用的是athrow指令 + exception_table匹配过程。
使用场景与陷阱:
- 接口方法声明
throws IOException,实现类抛出MyBusinessException extends Exception→ 编译失败,除非后者也继承IOException或声明为RuntimeException - 泛型方法里
throws T extends Throwable是非法的——类型擦除后无法生成有效的exception_table条目,编译器直接拒斥 - 使用Lombok的
@SneakyThrows本质是把检查异常包装成RuntimeException再抛出,绕过了throws检查,但exception_table里依然只有RuntimeException的条目
异常对象创建开销主要来自fillInStackTrace()
每次new一个异常实例,JVM默认调用fillInStackTrace(),遍历当前线程栈帧、提取类/方法/行号信息,这部分耗时可达微秒级——在高频路径(如协议解析循环)里累积起来很可观。
性能优化建议:
- 对已知固定场景的异常(如HTTP 404对应
NotFoundException),可重写fillInStackTrace()直接返回this,省去栈采集 - 不要用异常做流程控制,比如用
NoSuchElementException代替Map.containsKey()判断——异常实例化+栈填充+查找exception_table三重开销 - 注意
Exception子类和RuntimeException子类在此无区别,开销来源相同;区别只在是否强制声明
字节码层面真正关键的,从来不是你写了多少catch,而是exception_table有没有为对应异常类型配对上正确的范围和处理器地址——其余都是编译器和JVM按规范走的必然路径。漏掉构造函数、写错继承链、误信throws能控制运行时行为,这三处最容易卡住人。

















