Abel Garcia
Abel Garcia

Reputation: 178

Using ASM for bytecode analysis

I am evaluating the possibility of using ASM as framework for implementing some bytecode analysis. So far I have been playing with a few examples but there are a couple of things that I need to sort out: 1) I don't see how I can detect a method fully signature with the MethodVisitor class (full argument type names and formal names).

2) In case the .class file being analysed has the java source associated, how to link bytecode instructions with the line numbers in the source

3) How to differentiate between instance fields and static fields in a ClassVisitor

Upvotes: 0

Views: 1341

Answers (2)

Abel Garcia
Abel Garcia

Reputation: 178

1) Actually I manage to extract detailed method signature (arguments types and names and return type) as part of a MethodVisitor implementation. Remark: this only works if the class file was compiled including debug info.

@Override
public MethodVisitor visitMethod(int access, String name,
        String desc, String signature, String[] exceptions) {



    try {
        final LinkedList<String> parameters;
        final boolean isStaticMethod;

        Type[] args = Type.getArgumentTypes(desc);
        Type ret = Type.getReturnType(desc);

        parameters = new LinkedList<String>();            
        isStaticMethod = Modifier.isStatic(access);

        return new MethodVisitor(Opcodes.ASM5) {
            // assume static method until we get a first parameter name
            public void visitLocalVariable(String name, String description, String signature, Label start, Label end, int index) {
                if (isStaticMethod && parameters.size() < args.length) {
                    parameters.add(args[index].getClassName()+" " +name);
                } else if (index > 0 && parameters.size() < args.length) {
                    // for non-static the 0th arg is "this" so we need to offset by -1
                    parameters.add(args[index-1].getClassName() +" " +name);
                }
            }

            @Override
            public void visitEnd() {
                 System.out.println("Method: "+ret.getClassName()+" "+name+"("+String.join(", ", parameters)+")");
                super.visitEnd();
            }
        };
    } catch (Exception e) {
        throw e;
    }     

Which will produce the following output for an standard main:

Method: void main(java.lang.String[] args)

2) The arguments Label start and Label end include information about the corresponding source as long as there is a source included when the compilation took place.

3) See @Peter Lawrey reply.

Upvotes: 0

Peter Lawrey
Peter Lawrey

Reputation: 533530

1) I don't see how I can detect a method fully signature with the MethodVisitor class (full argument type names and formal names).

You can't. The ClassVisitor receives a call like

public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) 

and before you return the MethodVistor, you need to capture the information from the parameters you are interested in.

If the code was compiled with debugging information, you can obtain the parameter and local variable names with visitLocalVariable

2) In case the .class file being analysed has the java source associated, how to link bytecode instructions with the line numbers in the source

The code in the method will have source information "instruction" in the form of a visitLabel

3) How to differentiate between instance fields and static fields in a ClassVisitor

By the access modifier. Use Modifier.isStatic(access)

Upvotes: 2

Related Questions