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)
is called; or,printStackTrace()
and exit)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?
EDIT: 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.
If you call System.exit()
the program exits immediately without finally
being called.
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.
An infinite loop would also prevent a finally being called.
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();
}
prints
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
Note: in each case the thread kept running, even after SO, OOME, Interrupted and Thread.stop()!