finally {}块不会执行的情况是什么?

ast*_*eri 31 java jvm try-catch try-catch-finally

在Java try{} ... catch{} ... finally{}块中,finally{}无论try/catch中发生什么,通常都认为其中的代码是"保证"运行的.但是,我知道至少有两种情况不会执行:

  • 如果System.exit(0)被召唤; 要么,
  • 如果异常被抛到JVM并且发生默认行为(即printStackTrace()退出)

是否有任何其他程序行为会阻止finally{}块中的代码执行?代码在什么具体条件下执行?

编辑:正如NullUserException指出的那样,第二种情况实际上并非如此.我认为这是因为标准错误中的文本在标准输出之后打印出来,防止文本在没有向上滚动的情况下被看到.:) 道歉.

Pet*_*rey 33

如果你调用System.exit()程序立即退出而不finally被调用.

JVM崩溃,例如Segmentation Fault,也会阻止最终被调用.即JVM此时立即停止并生成崩溃报告.

无限循环也会阻止最终被调用.

抛出Throwable时始终会调用finally块.即使你调用Thread.stop()ThreadDeath也会触发一个在目标线程中抛出的东西.这可以被捕获(它是一个Error)并且将调用finally块.


public static void main(String[] args) {
    testOutOfMemoryError();
    testThreadInterrupted();
    testThreadStop();
    testStackOverflow();
}

private static void testThreadStop() {
    try {
        try {
            final Thread thread = Thread.currentThread();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    thread.stop();
                }
            }).start();
            while(true)
                Thread.sleep(1000);
        } finally {
            System.out.print("finally called after ");
        }
    } catch (Throwable t) {
        System.out.println(t);
    }
}

private static void testThreadInterrupted() {
    try {
        try {
            final Thread thread = Thread.currentThread();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    thread.interrupt();
                }
            }).start();
            while(true)
                Thread.sleep(1000);
        } finally {
            System.out.print("finally called after ");
        }
    } catch (Throwable t) {
        System.out.println(t);
    }
}

private static void testOutOfMemoryError() {
    try {
        try {
            List<byte[]> bytes = new ArrayList<byte[]>();
            while(true)
                bytes.add(new byte[8*1024*1024]);
        } finally {
            System.out.print("finally called after ");
        }
    } catch (Throwable t) {
        System.out.println(t);
    }
}

private static void testStackOverflow() {
    try {
        try {
            testStackOverflow0();
        } finally {
            System.out.print("finally called after ");
        }
    } catch (Throwable t) {
        System.out.println(t);
    }
}

private static void testStackOverflow0() {
    testStackOverflow0();
}
Run Code Online (Sandbox Code Playgroud)

版画

finally called after java.lang.OutOfMemoryError: Java heap space
finally called after java.lang.InterruptedException: sleep interrupted
finally called after java.lang.ThreadDeath
finally called after java.lang.StackOverflowError
Run Code Online (Sandbox Code Playgroud)

注意:在每种情况下,线程都保持运行,即使在SO,OOME,Interrupted和Thread.stop()之后!

  • 线程被杀后,我很惊讶它跑了.[文档](http://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html)说"如果执行try或catch代码的线程被中断或终止,则finally块**可能不会**即使整个申请仍在继续,也要执行." 有趣的是,它[曾经说过](http://web.archive.org/web/20090209025948/http://java.sun.com/docs/books/tutorial/essential/exceptions/finally.html)"终于块**不会**执行" (2认同)

Jer*_*her 9

try块中的无限循环.

损坏的RAM?程序不再按书面运行?我实际上已经在DOS机器上调试了一次.