How does the JVM guarantee execution of the finally block?
exception, java, jvm, try-catch
Solution
Compile this little program (I realized I should have used your example, but it makes no difference)
public static void main(String[] args) {
try {
Float s = Float.parseFloat("0.0327f");
} finally {
System.out.println("hello");
}
}
I used
>java -version
java version "1.8.0-ea" // should be same for 7
Java(TM) SE Runtime Environment (build 1.8.0-ea-b118)
Java HotSpot(TM) 64-Bit Server VM (build 25.0-b60, mixed mode)
And then execute
javac -v -c <fully qualified class name>
to get the bytecode. You will see something like
public static void main(java.lang.String[]);
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=3, args_size=1
0: ldc #2 // String 0.0327f
2: invokestatic #3 // Method java/lang/Float.parseFloat:(Ljava/lang/String;)F
5: invokestatic #4 // Method java/lang/Float.valueOf:(F)Ljava/lang/Float;
8: astore_1
9: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
12: ldc #6 // String hello
14: invokevirtual #7 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
17: goto 31
20: astore_2
21: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
24: ldc #6 // String hello
26: invokevirtual #7 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
29: aload_2
30: athrow
31: return
Exception table:
from to target type
0 9 20 any
20 21 20 any
LineNumberTable:
line 10: 0
line 12: 9
line 13: 17
line 12: 20
line 14: 31
StackMapTable: number_of_entries = 2
frame_type = 84 /* same_locals_1_stack_item */
stack = [ class java/lang/Throwable ]
frame_type = 10 /* same */
You'll notice the code inside the `finally` appears twice, once before the `goto` and once after. You'll also notice the `Exception table` which specifies which statement to go to if an exception occurs at some line.
So if any exception happens between statement 0-9, go to line 20 and execute the everything inside the `finally`, after the `goto`. If no exception occurs, execute the `finally` and then execute the `goto` skipping the `finally` after the `goto`.
In all cases you will have executed the code inside the `finally` block.
Other Exception not being explicitly handled
With a `finally` block, an `Exception table` entry will be created that will handle any type of `Throwable`.
Here's a listing of the bytecode instructions.
Problem
This question is aimed at how the JVM is able to guarantee the execution of a finally block (provided the JVM doesn't crash and the thread is not interrupted or exited). Prompted by an interview question, I am trying to understand how the JVM is able to ensure a finally block is executed even in strange circumstances... Consider the following code: ``` try{ int[] someArray = new int[10]; int invalid = someArray[10]; } catch(IndexOutOfBoundsException e){ throw new RuntimeException("Other Exception"); } finally{ //close open files or HTTP connections etc. } ``` While this may be an odd circumstance, the finally block is still guaranteed to be executed despite the Other Exception not being explicitly handled. How does the JVM handle situations like this? My Thoughts: From what I understand and have read so far, when an unhandled exception is encountered, control is transferred from the current thread (to that thread's `ThreadGroup` I think). Could there be some provision in the `ThreadGroup` that checks for finally blocks that need executing? The only other thing I can think of is perhaps the address of the finally block is stored somewhere. Then JVM does a goto when an exception is detected and returns to the exception when the finally block has finished execution. Can anyone clarify how this process actually happens?