As it is said in MethodVisitor.visitFrame documentation :
" .......
local - .....Reference types are represented by String objects (representing
internal names), and uninitialized types by Label objects (this label
designates the NEW instruction that created this uninitialized value)."
That means that such label object should ALWAYS be just before the appropriate
NEW instruction , this is not always true . Try the following :
run ASMLifier on the following method , taken from org/objectweb/asm/Type :
public static Type getObjectType(final String internalName) {
char[] buf = internalName.toCharArray();
return new Type(buf[0] == '[' ? ARRAY : OBJECT, buf, 0, buf.length);
}
the produced output is:
{
mv = cw.visitMethod(ACC_PUBLIC +
ACC_STATIC, "getObjectType", "(Ljava/lang/String;)
LJFBackComp/org/objectweb/asm/Type;", null, null);
mv.visitCode();
Label l0 = new Label();
mv.visitLabel(l0);
mv.visitLineNumber(217, l0);
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "toCharArray", "()[C");
mv.visitVarInsn(ASTORE, 1);
Label l1 = new Label();
mv.visitLabel(l1); <-------------------------------------
mv.visitLineNumber(218, l1); <-------------------------------------
mv.visitTypeInsn(NEW, "JFBackComp/org/objectweb/asm/Type"); <------------
mv.visitInsn(DUP);
mv.visitVarInsn(ALOAD, 1);
mv.visitInsn(ICONST_0);
mv.visitInsn(CALOAD);
mv.visitIntInsn(BIPUSH, 91);
Label l2 = new Label();
mv.visitJumpInsn(IF_ICMPNE, l2);
mv.visitIntInsn(BIPUSH, 9);
Label l3 = new Label();
mv.visitJumpInsn(GOTO, l3);
mv.visitLabel(l2);
mv.visitFrame(Opcodes.F_FULL, 2, new Object[] {"java/lang/String", "[C"}, 2,
new Object[] {l1, l1});
mv.visitIntInsn(BIPUSH, 10);
mv.visitLabel(l3);
mv.visitFrame(Opcodes.F_FULL, 2, new Object[] {"java/lang/String", "[C"}, 3,
new Object[] {l1, l1, Opcodes.INTEGER});
mv.visitVarInsn(ALOAD, 1);
mv.visitInsn(ICONST_0);
mv.visitVarInsn(ALOAD, 1);
mv.visitInsn(ARRAYLENGTH);
mv.visitMethodInsn
(INVOKESPECIAL, "JFBackComp/org/objectweb/asm/Type", "<init>", "(I[CII)V");
mv.visitInsn(ARETURN);
Label l4 = new Label();
mv.visitLabel(l4);
mv.visitLocalVariable("internalName", "Ljava/lang/String;", null, l0, l4, 0);
mv.visitLocalVariable("buf", "[C", null, l1, l4, 1);
mv.visitMaxs(6, 2);
mv.visitEnd();
}
the expected order of arrowed instructions should be :
mv.visitLabel(l1);
mv.visitTypeInsn(NEW, "JFBackComp/org/objectweb/asm/Type");
mv.visitLineNumber(218, l1);
The problem is actually inside ClassReader , which does not takes that into
consideration . I can propose to move visitLineNumer invockation/s to the
end ,just where visitLocalVariable are .