Strange exception table entry produced by Sun's javac
There are only two possible explanations: the compiler contains a bug or it's placing a kind of watermark for obscure reasons.
That entry is certainly bogus because any exception thrown by a finally block itself must send execution flow to outer exception handler or finally block, but never "run again" the same finally block.
Also, a good evidence that it's a bug/watermark, is the fact that Eclipse (and perhaps other Java compilers) are not generating such entry, and even so Eclipse-generated classes work fine on Sun's JVM.
That said, this post is interesting because it seems that the class file is valid and verified. If I were a JVM implementor, I would ignore that entry and fill a bug for Sun/Oracle!
Looking at the OpenJDK 7 source code, I would venture to guess the reason for
that last 28 29 28 any
exception table entry is because the code that
handles the astore
bytecode (see code starting at line 1871) can
throw an java.lang.LinkageError
exception if the popped value
from the operand stack is not a returnAddress
or reference
type (see the
Java Virtual Machine Specification for astore) and they want this
error condition to show up on the stack trace.
In the event that there is a bad operand type on the operand stack, the JVM will
clear the operand stack (getting rid of that bad operand), put a LinkageError
on the operand stack, and execute the astore
bytecode again, this time
successfully executing the astore
bytecode using a JVM provided LinkageError
object reference. See the athrow documentation for more information.
I would greatly suspect the root cause of throwing a LinkageError
during
astore
processing is due to the complexities JSR/RET subroutines introduce into bytecode verification (OpenJDK changes
6878713, 6932496 and 7020373 are
recent evidence of JSR
's continued complexity; I'm sure Sun/Oracle has other
closed source tests that we're not seeing in OpenJDK). The OpenJDK 7020373 change uses LinkageError
to validate/invalidate test results.
My understanding is that the second exception table entry is the implicit catch everything clause added by the compiler to cover any exceptions/errors thrown in the body or the catch handlers and the third entry is the guard on that implicit catch to force the flow through the finally execution.