Suppose we compile this method using Java 6+ compiler:
void test(int x) {
try {
x += 777;
} finally {
x -= 333;
}
}
The disassembled code would look like this:
test(I)V
TRYCATCHBLOCK L0 L1 L2 null
TRYCATCHBLOCK L2 L3 L2 null
L0 // Start of try block
IINC 1 777 // The body of try block
L1 // Start of finally block in case of successful execution
IINC 1 -333 // Body of finally block
GOTO L4 // End of 'success' finally block
L2 // Start of finally block in case of exception
ASTORE 2 // Remember exception
L3
IINC 1 -333 // Duplicated body of finally block
ALOAD 2 // Load remembered exception
ATHROW // Rethrow the exception
L4 // End of try/finally
RETURN
L5
Obviously, this declaration specifies the "try" section and the beginning of the "finally" block:
TRYCATCHBLOCK L0 L1 L2 null
But the next declaration looks strange:
TRYCATCHBLOCK L2 L3 L2 null
Why does the Java compiler protect the exception while remembering it, and why does it specify itself as the handler recursively (i.e. the two L2
s)?
catch
instead of finally?TRYCATCHBLOCK L0 L1 L2 java/lang/Exception