Adrninistrator / java-callgraph2

Programs for producing static call graphs for Java programs.
Apache License 2.0
184 stars 66 forks source link

如何进行源代码级别的处理? #36

Open nhjclxc opened 8 months ago

nhjclxc commented 8 months ago

如何进行源代码级的处理,假设我现在有如下.java文件,我想得到他的调用关系,但是我不想编译为.class或.jar,本项目是否支持? public class Test { public static void main(String[] args) { String str = fun1(61, "asd"); System.out.println("str = " + str); } private static String fun1(int i, String asd) { if (i > 10){ return fun2(i * 10) + asd; } return fun3((int)(i * 0.1)) + asd; } private static String fun2(int i) { return fun3(i); } private static String fun3(int v) { return v * 10 + ""; } }

Adrninistrator commented 8 months ago

用javaparser是可以分析java源码的,但是java源码分析会遇到的问题会更多,用class或者jar包来分析更适合一些,或者是源码和class结合起来分析,以class为主

nhjclxc commented 8 months ago

用javaparser是可以分析java源码的,但是java源码分析会遇到的问题会更多,用class或者jar包来分析更适合一些,或者是源码和class结合起来分析,以class为主

你好,我现在就是有一个需求需要直接处理一个方法级别的函数调用关系?请问使用你的项目能不能进行分析?

nhjclxc commented 8 months ago

用javaparser是可以分析java源码的,但是java源码分析会遇到的问题会更多,用class或者jar包来分析更适合一些,或者是源码和class结合起来分析,以class为主

还有就是method_call.txt里面的数据实在哪里写入的,我先知道method_call.txt文件每一行的最后那些数字的含义

Adrninistrator commented 8 months ago

这个项目只支持分析class文件,不建议用javaparser分析源码获得调用关系,效果没有class好

method_call文件格式可以参考 https://github.com/Adrninistrator/java-callgraph2/blob/main/docs/file_format.md

nhjclxc commented 8 months ago

这个项目只支持分析class文件,不建议用javaparser分析源码获得调用关系,效果没有class好

method_call文件格式可以参考 https://github.com/Adrninistrator/java-callgraph2/blob/main/docs/file_format.md

现在项目里面是否支持将method_call.txt里面的数据转化为dot语言表示的文件?

Adrninistrator commented 8 months ago

项目没有支持转换为dot语言表示的文件 之前有人试过用graphviz把输出的文件生成调用图,数据太多以后会非常慢

nhjclxc commented 8 months ago

项目没有支持转换为dot语言表示的文件 之前有人试过用graphviz把输出的文件生成调用图,数据太多以后会非常慢

你好,我想对你的项目进行二次开发以支持源代码级的方法调用,能不能对你的项目进行二次开发?你能给我提供一些思路吗?

Adrninistrator commented 8 months ago

源码用javaparser分析,这个项目分析class文件是用的bcel,这两个的差别还是比较大,分析源码需要专门做处理 javaparser用visitor模式,分析MethodCallExpr就可以获得源码里的方法调用

Adrninistrator commented 8 months ago

下面是chatgpt给出的示例代码,看基本信息是能获取到了,可以试一下效果,再调试一下看数据结构

要通过JavaParser的Visitor分析MethodCallExpr并获得方法之间的调用关系,你可以按照以下步骤进行:

创建一个类,实现VoidVisitorAdapter接口,并重写visit(MethodCallExpr, arg)方法。这个方法会在遍历抽象语法树(AST)时,每次遇到一个MethodCallExpr节点时被调用。

import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;

public class MethodCallVisitor extends VoidVisitorAdapter<Void> {
    @Override
    public void visit(MethodCallExpr n, Void arg) {
        // 在这里处理MethodCallExpr节点
        super.visit(n, arg);
    }
}

在visit(MethodCallExpr, arg)方法中,获取当前节点的名称和所属类的名称,并将它们存储到一个数据结构中。同时,递归遍历当前节点的所有子节点,以便分析更深层次的方法调用关系。这里我们可以使用一个Map来存储方法调用关系,其中键为方法名,值为一个List,表示该方法被哪些其他方法调用过。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MethodCallVisitor extends VoidVisitorAdapter<Void> {
    private Map<String, List<String>> callGraph = new HashMap<>();

    @Override
    public void visit(MethodCallExpr n, Void arg) {
        String methodName = n.getNameAsString();
        String className = n.resolve().getQualifiedName();

        // 更新方法调用关系
        if (!callGraph.containsKey(methodName)) {
            callGraph.put(methodName, new ArrayList<>());
        }
        callGraph.get(methodName).add(className);

        // 递归遍历子节点
        super.visit(n, arg);
    }

    public Map<String, List<String>> getCallGraph() {
        return callGraph;
    }
}

在分析完整个AST后,调用getCallGraph()方法来获取方法调用关系的数据结构。你可以将它输出到控制台,或者将它写入文件以供后续分析使用。

import java.io.FileWriter;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        // 解析Java源代码
        CompilationUnit cu = JavaParser.parse(new File("MyClass.java"));

        // 遍历AST并分析方法调用关系
        MethodCallVisitor visitor = new MethodCallVisitor();
        visitor.visit(cu, null);

        // 输出方法调用关系
        Map<String, List<String>> callGraph = visitor.getCallGraph();
        for (String methodName : callGraph.keySet()) {
            System.out.println(methodName + " is called by:");
            for (String className : callGraph.get(methodName)) {
                System.out.println("- " + className);
            }
        }

        // 将方法调用关系写入文件
        try (FileWriter writer = new FileWriter("callgraph.txt")) {
            for (String methodName : callGraph.keySet()) {
                writer.write(methodName + " is called by:\n");
                for (String className : callGraph.get(methodName)) {
                    writer.write("- " + className + "\n");
                }
                writer.write("\n");
            }
        }
    }
}

这样,你就可以使用JavaParser的Visitor分析MethodCallExpr,并获得方法之间的调用关系了。需要注意的是,这只是一个简单的例子,实际的分析可能会更加复杂和耗时。