According to Java Language Specification, Section §14.20.2
A try statement with a finally block is executed by first executing the try block. Then there is a choice:
- If execution of the try block completes normally, then the finally block is executed, and then there is a choice:
- If the finally block completes normally, then the try statement completes normally.
- If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S
If I interpret it correctly then after execution of try block finally is invoked, But how all this works and why I got the output,
public static int TestTryFinallyBlock()
{
int i =0;
try
{
i= 10; //Perform some more operation
return i;
}
finally
{
i = 40;
}
}
public static void main( String[] args )
{
int i1 = TestTryFinallyBlock(); //Here the output was 10 not 40
}
I want to know how this thing produced output 10.
Is that when try block is executed and return statement is encountered the output value is already pushed to stack, and then the finally block is executed
I know that return is encountered first then finally blocks runs so output is 10, but
How jvm interpret or how the try finally block is handled or converted by jvm?
Is that jvm uses GOTO section jump section to go to finally section or the stack is already maintained?
After a little search and seeing what byte codes were generated, I found that actually there are no finally blocks as it seems and no jump or goto statements generated by JVM.
The above code is translated something as (if I interpret byte code correctly, If I am wrong please do correct me)
Point to Note: If
'i'
would have been a reference to a mutable class object and the contents of the object were changed in the finally block, then those changes would have been reflected in the returned value too.Now the value of i is 40 but you are not getting 40, because you got(
returned
) the value before making it 40.it's like
Though not a good practice, Just for demo.
Now the value of 40 you'l get in i.
*As a side note:*never write any business logic other than resource clean up. That's kills readability and causes bugs.
This is because of the way the return statement function and the way it interact with a try with finally statement.
The Section §14.17 of the JLS describe the return statement.
The last sentence indicates that if the expression of the return statement is evaluated normally, then the return statement completes abrutptly. In your example, the
try
block terminates abrutply because of thereturn
statement and the reason being areturn
value 10 (i
is evaluated to value 10).Since in your example the
return
is in a try with finally block, Section §14.20.2 of the JLS tells us what happens next:So, since the
try
block terminated abruptly because of the return statement being evaluated to value 10, and because the finally block completes normally, then the method returns 10.Compiling Finally
Compilation of a try-finally statement is similar to that of try-catch. Prior to transferring control outside the try statement, whether that transfer is normal or abrupt, because an exception has been thrown, the finally clause must first be executed. For this simple example:
the compiled code is:
There are four ways for control to pass outside of the try statement: by falling through the bottom of that block, by returning, by executing a break or continue statement, or by raising an exception.
To know more about how javac interprets the finally block .Please refer JLS - 3.13. Compiling finally
When you enter the return, the method is already prepared to return 10. 10 is on the stack as the return value. The finally block is executed and sets
i
to 40--but thati
is not the same location as the return value. Now if there's a side effect like:40 will be printed.