12

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 L2s)?

6
  • Does the same happen if you use catch instead of finally? – Devolus Jan 9 '14 at 8:29
  • @Devolus No. It adds single TRYCATCHBLOCK L0 L1 L2 java/lang/Exception – ponomandr Jan 9 '14 at 10:16
  • 1
    Same question on SO a few years ago: stackoverflow.com/questions/6386917/… – Daniel W. Steinbrook Feb 28 '14 at 23:04
  • I agree with Devolus. I've never actually seen try{}finally{} in production code. – avgvstvs Mar 19 '14 at 2:39
  • Daniel, not the same question. The question "from a few years ago" explicitly states that his case occurs even with the presence of a catch block. – avgvstvs Mar 19 '14 at 2:40
1

A guess. As we can can see there is no actual duplication of code, the multiple trycatch blocks function as goto labels under different cases of what failed or not (since a finally clause is also present). If you follow the program flow you can see that no duplication takes place.

1

I just disassembled this using java 8 compiler and the second trycatchblock is no longer being generated

test(I)V
   TRYCATCHBLOCK L0 L1 L2 null
  L0
   IINC 1 777
  L1
   IINC 1 -333
  L3
   GOTO L4
  L2
   FRAME SAME1 java/lang/Throwable
   ASTORE 2
   IINC 1 -333
   ALOAD 2
   ATHROW
  L4
   FRAME SAME
   RETURN
  L5

My guess is this is some legacy handling that is ignored by the JVM

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.