Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does the JVM guarantee execution of the finally block?

Tags:

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?

like image 644
Joel Avatar asked Jan 07 '14 03:01

Joel


People also ask

Is finally block in Java guaranteed to be called?

Java finally block is a block used to execute important code such as closing the connection, etc. Java finally block is always executed whether an exception is handled or not. Therefore, it contains all the necessary statements that need to be printed regardless of the exception occurs or not.

Why finally block always executed Java?

A finally block is always get executed whether the exception has occurred or not. If an exception occurs like closing a file or DB connection, then the finally block is used to clean up the code. We cannot say the finally block is always executes because sometimes if any statement like System.

What is the use of the finally block is finally block in Java guaranteed to be called when finally block is not called?

The finally block in java is used to put important codes such as clean up code e.g. closing the file or closing the connection. The finally block executes whether exception rise or not and whether exception handled or not. A finally contains all the crucial statements regardless of the exception occurs or not.

Is the finally block always executed?

A finally block always executes, regardless of whether an exception is thrown. The following code example uses a try / catch block to catch an ArgumentOutOfRangeException.


1 Answers

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.

like image 62
Sotirios Delimanolis Avatar answered Sep 27 '22 21:09

Sotirios Delimanolis