在什么情况下 finally {} 块不会执行?
在 Java try{} ... catch{} ... finally{}
块中,finally{}
中的代码通常被认为是保证"无论 try/catch 中发生什么,都运行.但是,我知道它至少不会执行的两种情况:
In a Java try{} ... catch{} ... finally{}
block, code within the finally{}
is generally considered "guaranteed" to run regardless of what occurs in the try/catch. However, I know of at least two circumstances under which it will not execute:
- 如果
System.exit(0)
被调用;或者, - 如果异常一直抛出到 JVM 并且发生默认行为(即,
printStackTrace()
并退出)
- If
System.exit(0)
is called; or, - if an Exception is thrown all the way up to the JVM and the default behavior occurs (i.e.,
printStackTrace()
and exit)
是否有任何其他程序行为会阻止 finally{}
块中的代码执行?代码会在什么特定条件下执行?
Are there any other program behaviors that will prevent the code in a finally{}
block from executing? Under what specific conditions will the code execute or not?
正如 NullUserException 所指出的,第二种情况实际上是不正确的.我认为这是因为标准错误中的文本在标准输出之后打印,防止在不向上滚动的情况下看到文本.:) 抱歉.
As NullUserException pointed out, the second case is actually not true. I thought it was because the text in standard error printed after that in standard out, preventing the text from being seen without scrolling up. :) Apologies.
推荐答案
如果调用System.exit()
程序立即退出而不调用 finally
.
JVM 崩溃,例如Segmentation Fault,也会阻止 finally 被调用.即 JVM 在此时立即停止并生成崩溃报告.
A JVM Crash e.g. Segmentation Fault, will also prevent finally being called. i.e. the JVM stops immediately at this point and produces a crash report.
无限循环也会阻止 finally 被调用.
An infinite loop would also prevent a finally being called.
finally 块总是在抛出 Throwable 时调用.即使您调用 Thread.stop() 触发 ThreadDeath
在目标线程中被抛出.这可以被捕获(这是一个 Error
) 并且 finally 块将被调用.
The finally block is always called when a Throwable is thrown. Even if you call Thread.stop() which triggers a ThreadDeath
to be thrown in the target thread. This can be caught (it's an Error
) and the finally block will be called.
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、Interrupted 和 Thread.stop() 之后也是如此!
Note: in each case the thread kept running, even after SO, OOME, Interrupted and Thread.stop()!
相关文章