乐趣区

JavaFinally-代码块不会执行的情况

finally 的作用

finally 是 Java 异常处理机制的组成部分,它保证了代码块中的代码一定要被执行。通常我们会将资源释放的代码写在 finally 代码块中,如 I/O 的关闭、数据库连接的关闭等。

但是也会存在 finally 代码块中的代码不会执行的情况,本文就是总结了这些情况。

finally 代码块不会执行的情况

之前在网上的帖子看到有一种情况是叫做”不进入 try 代码块“,这不废话吗,不进入 try 当然不会执行 finally 代码块。所以本文讨论的是进入 try 代码块后 finally 代码块不执行的情况。

1. 虚拟机被终止 System.exit();

System.exit(0) 的作用是中止当前正在运行的 Java 虚拟机。如果虚拟机被中止,程序也会被终止,所以在它后面的代码都不会被执行,即便是 finally 代码块也同样不会执行。

private static void demo1() {
    try {System.out.println("执行 try 代码块");
        System.exit(0);
    } finally {System.out.println("开始执行 finally 代码块");
    }
}

/** 控制台输出:执行 try 代码块

**/

2. try 代码块无限循环

这是由于业务逻辑的原因,一直在执行 try 代码块的业务并且永远无法终止,try 代码块都没执行完,自然无法执行 finally 代码块。

private static void demo2() {
    try {while (true) {
            // do something
            System.out.println("执行 try 代码块");
        }
    } finally {System.out.println("开始执行 finally 代码块");
    }
}

/** 控制台输出:执行 try 代码块
执行 try 代码块
...(一直输出)**/

3. 在被中止的守护线程内

Java 中的线程可以分为守护线程和用户线程。当程序中所有的用户线程都终止时,虚拟机会 kill 所有的守护线程来终止程序。

当 try-finally 代码块存在于守护线程,而此守护线程因用户线程被销毁而终止时,该守护线程不会继续执行。

假设用户线程(main 线程)执行完毕后,作为守护线程的 thread 对象中的 try 代码块还没有执行结束,当用户线程执行结束后,此时已不存在用户线程,虚拟机会强制中止守护线程 thread,导致 finally 代码块不会被执行。

private static void demo3() {Thread thread = new Thread(() -> {
            try {System.out.println("执行 try 代码块,等待 2s,等待主线程执行结束...");
                Thread.sleep(2000);
            } catch (InterruptedException e) {e.printStackTrace();
            } finally {System.out.println("开始执行 finally 代码块");
            }
        });
        thread.setDaemon(true);
        thread.start();}

/** 控制台输出:执行 try 代码块,等待 2s,等待主线程执行结束...

**/

参考博客

finally 块不被执行的情况总结

退出移动版