I have just encountered this following code:
public class TestFinally {
public static void main(String[] args) {
int returnValue = function();
System.out.println("Return value: " + returnValue);
}
public static int function() {
try {
return 1;
} catch (Exception e){
return 2;
} finally{
return 3;
}
}
}
It is without a doubt that running this code will yield an output of "Return value: 3".
However, I am curious as to:
- The mechanism of the innards in the JVM. Does anyone know if the VM actually replaces the return value on the stack by over-writing the first "return 1"? If so, where can I find more information on this.
- I have yet to find the use for a return in the finally mechanism that is used this way and allowed in the implemented in the JVM. If this code construct is used as a means to return error code, it is in my opinion there are better ways to log errors or return these error codes. Has anyone found a use for such a construct?
Many thanks in advance.
Cheers, Vern
The implementation is up to the JVM, and there are many JVMs. You could dig into OpenJDK's source code to see how it implements
finally
, but this wouldn't be the only way to do it. As far as the language is concerned, the important thing is the behavior.I don't understand point 2 -- why does
finally
exist? it is not as you suggest somehow just a means to return an error code. You don't have to return from withinfinally
at all. The construct exists to ensure that some kind of clean-up code is run after some section of code no matter how it terminates, whether normally or via exception or return.What I found in the Java language specification at least defines that your code snippet should return 3. Of course, it does not mention how the JVM should implement this, and what possible optimizations one could do.
Section 14.20.2 defines that
And the start of chapter14 (section 14.1 to be more precise) specifies what a normal and abrupt completion is. For example a
return
with a given value is an abrupt completion.Hence in this case, the
finally
block completes abruptly (reason:return
with a given value), so thetry
will complete abruptly for the same reason (and return 3). This is confirmed in section 14.17 about the return statement as wellFully explained Page:439=> http://docs.oracle.com/javase/specs/jls/se8/jls8.pdf
If evaluation of the Expression completes normally, producing a value V, then the return statement completes abruptly, the reason being a return with value V.
The preceding descriptions say "attempts to transfer control" rather than just "transfers control" because if there are any try statements (§14.20) within the method or constructor whose try blocks or catch clauses contain the return statement, then any finally clauses of those try statements will be executed, in order, innermost to outermost, before control is transferred to the invoker of the method or constructor. Abrupt completion of a finally clause can disrupt the transfer of control initiated by a return statement.
FWIW, I get a warning on function:
Ie. it tells me "finally block does not complete normally". I still get 3 as returned value no matter what.
Anyway, if I try this other example:
the output will be (obviously)
I have no idea how the JVM implements it, but the simplest way to look at it (at least conceptually) would be:
Very neat question indeed.