Skip to main content

Help needed generating StackMapTable for constructor

1 reply [Last post]
jrmacmillan
Offline
Joined: 2009-01-30
Points: 0

I work on a tool that does bytecode instrumentation, and I have been updating it to generate / update StackMapTable attributes for the new verifier, and I've run into a snag.

One of our modifications involves wrapping the entire method (offset 0 to original end of method) in an exception handler appended after the original method. Since there is a new basic block (the handler) I need to add a entry to the StackMapTable (generating one if there was not one already).

This works, except on constructors which still fail to verify. I suspect this has to do with the uninitialized this, although I admit I'm not entirely clear on why. I'm unable to come up with a StackMapTable that correctly verifies for what javap disassembles to:

$ javap -c Simple
public class Simple extends java.lang.Object{
public Simple();
Code:
0: aload_0
1: invokespecial #8; //Method java/lang/Object."":()V
4: return
5: athrow
Exception table:
from to target type
0 5 5 any

}

$ java -Xverify:all -XX:-FailOverToOldVerifier Simple
Exception in thread "main" java.lang.VerifyError: Stack map does not match the one at exception handler 5 in method Simple.()V at offset 1
Could not find the main class: Simple. Program will exit.

That's with a 1.6.0_11-b03 JRE.

I've tried a SAME_LOCALS_1_STACK_ITEM with a Throwable, a FULL_FRAME with empty frame, Throwable on stack, and a few other FULL frame variants, but I can't get it to verify. It fails at offset 0 or 1, depending on the map. I even tried adding a FULL_FRAME before and after the invokespecial, but I can't come up with anything that works.

I'm not alone; if I make the same modification with the fine ASM toolkit and ask it to generate the StackMapTable, it generates a FULL_FRAME with no frames and a Throwable on stack, which also fails to verify.

Now I know javac won't generate code like this, but is (or at least was) legal for the JVM prior to 1.6.

Any suggestions?

Thanks,
John

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
jrmacmillan
Offline
Joined: 2009-01-30
Points: 0

To answer my own question, the VM spec says "There must never be an uninitialized class instance in a local variable in code protected by an exception handler."

Since in constructors local 0 is an uninitialized instances, the code I described has never been legal, but the old verifier apparently never enforced it in this situation.

I still think this is unfortunate behaviour, in that it makes certain kinds of instrumentation in constructors very difficult (eg. anything that wants to guarantee being called on exit of the method, including from code before the instance is initialized).