0

I'm trying to use ASM to wrap a method in a try/finally block. Specifically, I am extending org.objectweb.asm.commons.AdviceAdapter and following the technique described "Using ASM framework to implement common bytecode transformation patterns" under "3.2.3 Insert Code before Method Exit".

I am also using LocalVariablesSorter (a superclass of AdviceAdapter) to add a local variable right at the method start which I use in the finally block.

I have a method that I am attempting to modify with ASM. The method takes three args and has no locals of its own:

class Example {
    public static int f4(int i, long l, int f) {
        return (int) (i + l + f);
    }
}

Since my finally block may be an exception handler target, I add a call so super.visitFrame(F_NEW, ...), passing the method parameters. Since this calls up to the super class, I expect my newLocal to be added to this frame by LocalVariablesSorter. But when running this through my ASM pipeline, Java 7 gives me the error java.lang.VerifyError: Bad local variable type in method Example.f4(IJI)I at offset 32.

Looking at the source of LocalVariablesSorter, in the visitFrame method, I see that it has a boolean changed and if not changed, visitFrame skips any consideration of any new locals I may be created. This changed boolean appears to only be set when upstream bytecode performs certain operations on variables that have had to be remapped due to using LocalVariablesSorter to create new locals (and no such operations occur in the f4() method above).

By applying this workaround:

       Field field = LocalVariablesSorter.class.getDeclaredField("changed");
       field.setAccessible(true);
       field.setBoolean(this, true);

I am able to pass Java 7's verifier. Also, using the TraceClassVisitor ASM utility, I see the difference in the stack map frame just before the start of the finally block:

before:

FRAME FULL [I J I] [java/lang/Throwable]

after my reflection hack (the new local I am adding is an int):

FRAME FULL [I J I I] [java/lang/Throwable]

I know I have not shared any of the surrounding code, but my question is more general. Is this changed boolean an erroneous optimization by LocalVariablesSorter? Or is it that I am misusing it somehow?

Patrick
  • 5,714
  • 4
  • 31
  • 36

1 Answers1

0

The LocalVariablesSorter.visitFrame(..) call doesn't add any locals, it only informs ASM to record information about additional frames. You need to add your locals by calling LocalVariablesSorter.newLocal(..).

Though generally, if you believe you found a bug in ASM, it is better to submit bug report to ASM issue tracker and provide test code that would allow to reproduce issue (e.g. a test class and complete transformation).

Eugene Kuleshov
  • 31,461
  • 5
  • 66
  • 67