如何在Java中找到方法调用的行号

时间:2014-11-23 15:56:29

标签: java java-bytecode-asm

我需要获取行号,在.class文件中调用特定方法。

我查看了How can I find all the methods that call a given method in Java?它返回调用方法的方法,但我也需要调用方法中的行号。

1 个答案:

答案 0 :(得分:1)

我通过稍微操作该链接上的代码来解决它

import java.io.InputStream;

import org.objectweb.asm.*;
import org.objectweb.asm.commons.*;

public class App{
    public static void main( String[] args ) {
        try {
            Test test = new Test();

                test.findCallers();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}


class Test {
    private String targetClass;
    private Method targetMethod;

    private AppClassVisitor cv;

    class AppMethodVisitor extends MethodVisitor {
        boolean callsTarget;
        int line;

        public AppMethodVisitor() { 
            super(Opcodes.ASM5); 
        }

        public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
            if (owner.equals("Fibonacci") && name.equals("join") && desc.equals("()V")) {
                callsTarget = true;
                System.out.println("Function join called on " + this.line);
            }
            super.visitMethodInsn(opcode, owner, name, desc, itf);
        }

        public void visitCode() {
            callsTarget = false;
        }

        public void visitLineNumber(int line, Label start) {
            this.line = line;
        }

        public void visitEnd() {
            if (callsTarget){
                System.out.println(cv.className + cv.methodName + cv.methodDesc  + line);
            }
        }
    }

    class AppClassVisitor extends ClassVisitor {
        private AppMethodVisitor mv = new AppMethodVisitor();

        public String className;
        public String methodName;
        public String methodDesc;

        public AppClassVisitor() { 
            super(Opcodes.ASM5); 
        }

        public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
            className = name;
        }

        public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
            methodName = name;
            methodDesc = desc;

            return mv;
        }
    }

    public void findCallers() throws Exception {
        InputStream stream = App.class.getResourceAsStream("Fibonacci.class");
        ClassReader reader = new ClassReader(stream);
        cv = new AppClassVisitor();

        reader.accept(cv, 0);

        stream.close();
    }
}

Fibonacci.java内容:

public class Fibonacci extends Thread{
    int n;
    int result;

    public Fibonacci(int n){
        this.n = n;
    }

    public void run(){
        if((n == 0) || (n == 1)){
            result = 1;
        }else{
            Fibonacci f1 = new Fibonacci(n - 1);
            Fibonacci f2 = new Fibonacci(n - 2);

            f1.start();
            f2.start();

            try{
                f1.join();
                f2.join();
            }catch(InterruptedException e){
                e.printStackTrace();
            }

            result = f1.getResult() + f2.getResult();
        }
    }

    public int getResult(){
        return result;
    }

    public static void main(String[] args) {
        Fibonacci f1 = new Fibonacci(5);
        f1.start();

        try{
            f1.join();
        }catch(InterruptedException e){
            e.printStackTrace();
        }

        System.out.println("Answer is " + f1.getResult());
    }
}