fast throw 是 jvm 自动触发的底层优化机制,当 nullpointerexception 等五种内置异常在同一字节码位置高频抛出时,c2 编译器复用无堆栈模板异常以提升性能;可通过 -xx:-omitstacktraceinfastthrow 关闭,需依场景权衡。

HotSpot 的 Fast Throw 不是开发者主动“优化”的行为,而是 JVM 在运行时自动触发的底层性能优化机制。它本身不可编程干预,但你可以理解它的作用逻辑,并通过配置和代码习惯来控制其影响。
Fast Throw 是什么
当某些内置异常(如 NullPointerException、ArrayIndexOutOfBoundsException、ArithmeticException 等)在**同一字节码位置被高频重复抛出**时,C2 JIT 编译器会识别该路径为“热点异常点”,随后不再每次新建异常对象并填充堆栈,而是复用一个预先创建、stack trace 为空、message 为空 的模板异常实例。
这样省去了:
- 调用
fillInStackTrace()遍历栈帧 - 解析方法符号与行号信息
- 为每个异常分配新对象内存
哪些异常会被 Fast Throw 影响
仅限以下五种隐式抛出的内置异常类型:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- NullPointerException
- ArrayIndexOutOfBoundsException
- ArrayStoreException
- ClassCastException
- ArithmeticException(仅限除零等 JVM 自动抛出场景)
手动 throw new NullPointerException("msg") 不触发 Fast Throw;自定义异常也完全不受影响。
如何让 Fast Throw “不生效”或便于排查
这不是“优化”,而是权衡——线上追求吞吐可保留它,调试阶段建议关闭:
- 启动时加参数:
-XX:-OmitStackTraceInFastThrow(关闭默认优化) - 验证是否生效:打印异常后检查
e.getStackTrace().length == 0是否消失 - 配合
-XX:+PrintCompilation观察目标方法是否完成 C2 编译并进入 fast throw 状态 - 避免在循环/高频路径中故意触发相同 NPE(例如反复访问 null 字段),从源头减少触发条件
要不要关?看场景
生产环境频繁报错时,关闭 Fast Throw 会导致 CPU 上升——因为每次异常都真实爬栈、分配对象、格式化字符串。所以更推荐:
- 日常开发 / 测试环境:默认关闭,确保堆栈完整
- 线上稳定服务:保留开启,但配合监控告警+前置校验(如 Optional、Objects.requireNonNull)把异常拦截在发生前
- 出问题时临时加参数重启,拿到完整堆栈后再恢复
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










