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?