finally块几乎总执行,例外是System.exit()或JVM崩溃;try/catch/return后均执行finally;finally异常会覆盖原异常,应避免抛出。

在Java中,finally块几乎总是会执行,但存在少数明确的例外情况。理解这些边界条件,对编写健壮、可预测的资源清理逻辑至关重要。
正常流程下finally必定执行
只要try或catch块开始执行(哪怕只执行了一行),且未遇到JVM强制终止,finally就会被执行。这包括:
- try中无异常:执行完try后进入finally
- try中抛出异常并被catch捕获:执行完catch后进入finally
- try中抛出异常且未被捕获(向上抛):在异常传播前,先执行finally
- try或catch中含return语句:先计算return表达式的值(暂存),再执行finally,最后返回——red">finally里修改变量不影响已暂存的返回值,但若finally也写return,则会覆盖原返回值
JVM直接退出导致finally不执行
以下两种情况会绕过finally:
- System.exit(int):立即终止JVM,所有后续代码(包括finally)均不执行
- 底层崩溃或致命错误:如OutOfMemoryError触发JVM崩溃、kill -9强制杀死进程、断电等非可控场景
注意:Thread.stop()已被废弃,且即使使用也不保证finally执行;现代代码不应依赖它。
立即学习“Java免费学习笔记(深入)”;
线程被中断或销毁的误区
有人误以为线程中断(interrupt())或线程死亡会导致finally跳过,实际并非如此:
- 调用thread.interrupt()仅设置中断标志,不影响当前正在执行的try-finally结构
- 线程自然结束(run方法返回)或抛出未捕获异常,只要没调用System.exit,其内部的finally仍会执行
- 唯一例外是该线程正在执行System.exit(),此时整个JVM退出
finally中发生异常的影响
如果finally块自身抛出异常:
- 会覆盖try/catch中已发生的异常(原异常被丢弃)
- 若try和finally都抛异常,最终传播的是finally中的异常
- 因此建议在finally中避免抛出新异常,或确保清理操作本身足够安全(如用try-catch包裹close()调用)
例如:关闭资源时应写成if (res != null) try { res.close(); } catch (IOException ignored) {},而非直接调用close()。










