Search code examples
javajava-bytecode-asmbytecode-manipulationjvm-bytecode

ASM parameter numbering


Let's say I have a dummy class

public class B {
    public Object run(long v, String f){
        if(v == 2) {
            if(f.equals("x")) {
                return new Object();
            }
        }
        return null;
    }
}

asmifier will create the following for the run method:

{
mv = cw.visitMethod(ACC_PUBLIC, "run", "(JLjava/lang/String;)Ljava/lang/Object;", null, null);
mv.visitCode();
mv.visitVarInsn(LLOAD, 1);
mv.visitLdcInsn(new Long(2L));
mv.visitInsn(LCMP);
Label l0 = new Label();
mv.visitJumpInsn(IFNE, l0);
mv.visitVarInsn(ALOAD, 3);
mv.visitLdcInsn("x");
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
mv.visitJumpInsn(IFEQ, l0);
mv.visitTypeInsn(NEW, "java/lang/Object");
mv.visitInsn(DUP);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
mv.visitInsn(ARETURN);
mv.visitLabel(l0);
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitInsn(ACONST_NULL);
mv.visitInsn(ARETURN);
mv.visitMaxs(4, 4);
mv.visitEnd();
}

And I don't get this bit:

mv.visitVarInsn(ALOAD, 3);

The way I see it, there are only three arguments for run:

0: `this`
1: v:J
2: f:Ljava/lang/String

So why is f now loaded using 3 rather than 2?


Solution

  • This is because the Java Virtual Machine Specification chapter 2.6.1 says

    A value of type long or type double occupies two consecutive local variables.

    and

    The Java Virtual Machine uses local variables to pass parameters on method invocation.

    Therefore the arguments for your example are:

    0: `this`
    1: v:J
    3: f:Ljava/lang/String