在什么情况下,最终的 {} 块不会执行?

2022-09-01 07:39:16

在 Java 块中,通常认为 “保证”运行中的代码,而不管 try/catch 中发生了什么。但是,我知道至少有两种情况它不会执行:try{} ... catch{} ... finally{}finally{}

  • 如果 被调用;或System.exit(0)
  • 如果异常一直抛到JVM并且发生缺省行为(即,退出)printStackTrace()

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

编辑:正如NullUserException所指出的,第二种情况实际上是不正确的。我以为这是因为标准文本在标准错误之后打印出来,阻止了文本在不向上滚动的情况下被看到。:)道歉。


答案 1

如果调用 System.exit(),程序将立即退出,而不会被调用。finally

JVM崩溃(例如分段错误)也会阻止最终被调用。即,JVM 此时立即停止并生成崩溃报告。

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

最后一个块总是在抛出可抛出时调用。即使你调用 Thread.stop(),它会触发在目标线程中抛出的 ThreadDeath。这可以被捕获(这是一个错误),最后一个块将被调用。


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();
}

指纹

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

注意:在每种情况下,线程都会继续运行,即使在SO,OOME,中断和Thread.stop()之后也是如此!


答案 2

块中的无限循环。try

内存损坏?程序不再按编写运行?我实际上已经在DOS机器上调试过一次。


推荐