finally块并非绝对执行,其执行取决于jvm是否仍具备调度能力:outofmemoryerror等jvm级错误下可能执行但不可靠;system.exit()和halt()明确跳过;kill-9等系统强杀则零机会执行;finally自身异常会导致清理中断。

finally块在程序崩溃时通常不执行,但是否执行取决于崩溃的类型和严重程度。它不是“绝对兜底”,而是依赖JVM还能否调度字节码——一旦执行环境丧失基本能力,finally就失去运行基础。
OutOfMemoryError等JVM级错误:可能执行,但不可靠
这类错误属于JVM内部异常,尚未完全崩溃。多数情况下,finally仍会执行,因为JVM还能完成当前方法栈的退出流程。
- 例如申请超大数组触发OutOfMemoryError,catch捕获后,finally中的日志或简单清理语句大概率能输出
- 但若内存已极度紧张,连日志系统本身都分配不出对象,finally里的语句可能抛出新异常而中断
- StackOverflowError同理:栈空间耗尽后,能否进入finally取决于剩余栈帧是否足够支撑跳转
System.exit()与Runtime.halt():明确跳过,无例外
这是最常见也最容易被忽视的“崩溃等效”场景——程序逻辑主动终止JVM,finally彻底失效。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
-
System.exit(0)会触发shutdown hooks,但跳过所有未执行的finally -
Runtime.getRuntime().halt(0)更激进:不运行钩子、不调用finalize,连finally都“来不及响应” - 多见于测试强制退出、框架紧急熔断逻辑,需检查调用链中是否存在此类调用
操作系统强杀(如kill -9):零机会执行
这不是Java层的崩溃,而是进程被内核直接抹除——finally根本不会开始执行。
- JVM运行时上下文、线程堆栈、锁状态全部丢弃,无日志、无堆栈、无回调
- shutdown hooks、finalize、JNI卸载等Java层机制一并失效
- 文件未关闭、连接未释放、临时文件残留等问题由此产生,不能归咎于代码没写finally,而是设计上必须接受这种可能性
finally自身失败:执行了,但没完成
这是线上最隐蔽的问题——看似进了finally,实则中途崩溃或掩盖主异常。
- 在finally中调用
close()抛出IOException,又没捕获,导致原始业务异常被吞掉 - finally里发生NullPointerException,或再次调用
System.exit() - 正确做法是:每个资源关闭操作单独try-catch,用
addSuppressed()保留原始异常上下文
finally仍是资源清理的第一道防线,但它只对Java可控的控制流有效;面对系统级中断,它天然失能。关键保障要靠外部机制补位。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










