Kieran
Kieran

Reputation: 43

Accessing local variables in the ASM Java library

I'm trying to invoke a local variable when inserting a method. Thus far, I'm able to get the local variable in a Node but am having trouble actually accessing anything.

Here is my insertion stuff (it's very scrappy, I've been at this for a while and design stopped being my main priority some time ago):

        final ClassReader reader = new ClassReader("revel/reflection/test/SomeClass");
    final ClassNode classNode = new ClassNode();
    reader.accept(classNode, 0);
    for(final MethodNode mn : (List<MethodNode>)classNode.methods) {
        if(mn.name.equalsIgnoreCase("testLocals")) {
            final InsnList list = new InsnList();

            for(final LocalVariableNode local : (List<LocalVariableNode>)mn.localVariables) {
                System.out.println("Local Variable: " + local.name + " : " + local.desc + " : " + local.signature + " : " + local.index);
                if(local.desc.contains("String")) {
                    mn.visitVarInsn(Opcodes.ALOAD, local.index);
                    final VarInsnNode node = new VarInsnNode(Opcodes.ALOAD, 1);

                    list.add(node);
                    System.out.println("added local var '" + local.name + "'");
                }
            }

            final MethodInsnNode insertion = new MethodInsnNode(Opcodes.INVOKESTATIC, "revel/reflection/test/Test", "printLocalString", "(Ljava/lang/String;)V");
            list.add(insertion);
            mn.instructions.insert(list);
        }
    }

    ClassWriter writer = new ClassWriter(0);
    classNode.accept(writer);

    loadClass(writer.toByteArray(), "revel.reflection.test.SomeClass");
    SomeClass.testLocals(true);

the method it's trying to get into:

    public static void testLocals(boolean one) {
    String two = "hello local variables";
    one = true;
    int three = 64;
}

And it produces:

Local Variable: one : Z : null : 0
Local Variable: two : Ljava/lang/String; : null : 1
added local var 'two'
Local Variable: three : I : null : 2
Exception in thread "main" java.lang.VerifyError: Bad local variable type
Exception Details:
  Location:
    revel/reflection/test/SomeClass.testLocals(Z)V @0: aload_1
  Reason:
    Type top (current frame, locals[1]) is not assignable to reference type
  Current Frame:
    bci: @0
    flags: { }
    locals: { integer }
    stack: { }
  Bytecode:
    0000000: 2bb8 0040 1242 4c04 3b10 403d b12b     

        at revel.reflection.test.Test.main(Test.java:66)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at                         sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

Line 66 is SomeClass.testLocals(true); Can anyone shed any light on the situation?

Upvotes: 4

Views: 2707

Answers (1)

neuronaut
neuronaut

Reputation: 2709

It looks like your problem is with the line mn.instructions.insert(list); which is inserting the new instruction at the beginning of the list of all instructions for the method testLocals. In other words, you've put your use of the variable two before it is even declared or assigned a value. Try using mn.instructions.add(list); and see if that doesn't fix things.

Good luck!

Upvotes: 1

Related Questions