Ah! After spending half-an-hour in JLS and JVM Spec, I finally found the reason there in
JLS Section 14.20.2 
, specifically these lines:
If execution of the try block completes abruptly because of a throw of a value V, then there is a choice:
[...]
If the run-time type of V is not assignment compatible with a catchable exception class of any catch clause of the try statement, then the finally block is executed. Then there is a choice:
If the finally block completes normally, then the try statement completes abruptly because of a throw of the value V.If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and the throw of value V is discarded and forgotten).
And the
return statement in the
finally block results in abrupt completion of the
finally block. See
JLS Section 14.17 - return Statement, lower down the section:
It can be seen, then, that a return statement always completes abruptly.
So, the second rule in the above list is applicable here. Since
finally block completes abruptly due to a
return statement (
Reason S), the
try statement completes abruptly because of that
return statement. And hence your method returns 0.
Lesson of the day: You should never ever return from a
finally block, else be ready for surprises