Как исключить java стандартные библиотеки из графов вызовов, сгенерированных Soot? - PullRequest
0 голосов
/ 25 января 2020

Я сейчас работаю над автоматическим c инструментом для документирования кода. Для этого я использую Сажу для построения графа вызовов. Однако, похоже, что Саота включает стандартные библиотеки java в этот граф вызовов. Это, конечно, нежелательно, поскольку меня интересуют только те классы программы, для которых я буду генерировать документацию.

Это программа, которую я использовал для проверки графа:

    public static void main(String[] args) throws FileNotFoundException {

        List<String> argsList = new ArrayList<String>(Arrays.asList(new String[0]));
        argsList.addAll(Arrays.asList(new String[]{
            "-w",
            "-no-bodies-for-excluded",
            "-process-dir",
            args[1], //directory with the java files
            "-src-prec",
            "java",
            "-main-class",
            args[2] //main class
        }));

        String[] trueArgs = argsList.toArray(new String[0]);
        Main.v().run(trueArgs);
        CallGraph cg = Scene.v().getCallGraph();
        visit(cg , Scene.v().getEntryPoints().get(0));
    }

Со следующей функцией для перебора графа вызовов (взято из этот вопрос ):

    private static void visit(CallGraph cg, SootMethod method) {
          String identifier = method.getSignature();
          visited.put(method.getSignature(), true);
          dot.drawNode(identifier);
          // iterate over unvisited parents
          Iterator<MethodOrMethodContext> ptargets = new Sources(cg.edgesInto(method));
          if (ptargets != null) {
            while (ptargets.hasNext()) {
                SootMethod parent = (SootMethod) ptargets.next();
                if (!visited.containsKey(parent.getSignature())) visit(cg, parent);
            }
          }
          // iterate over unvisited children
          Iterator<MethodOrMethodContext> ctargets = new Targets(cg.edgesOutOf(method));
          if (ctargets != null) {
            while (ctargets.hasNext()) {
               SootMethod child = (SootMethod) ctargets.next();
               dot.drawEdge(identifier, child.getSignature());
               System.out.println(method + " may call " + child);
               if (!visited.containsKey(child.getSignature())) visit(cg, child);
            }
          }
    }

Однако во время тестирования я записывал такие вызовы:

[...]
<callgraphs.A: void <init>()> may call <java.lang.Object: void <init>()>
<java.lang.Thread: void <init>(java.lang.ThreadGroup,java.lang.Runnable)> may call <java.lang.Object: void <clinit>()>
<java.lang.Thread: void <init>(java.lang.ThreadGroup,java.lang.String)> may call <java.lang.Object: void <clinit>()>
<java.lang.Thread: void <init>(java.lang.ThreadGroup,java.lang.String)> may call <java.lang.Object: void <init>()>
<java.lang.Thread: void <init>(java.lang.ThreadGroup,java.lang.String)> may call <java.lang.Thread: void init(java.lang.ThreadGroup,java.lang.Runnable,java.lang.String,long)>
<java.lang.Thread: void <init>(java.lang.ThreadGroup,java.lang.String)> may call <java.lang.Object: void <init>()>
[...]

За этим следует множество звонков между java библиотеками.

Есть ли способ заставить Сагу просто игнорировать стандартные библиотеки java?

1 Ответ

0 голосов
/ 26 января 2020

Хорошо, я нашел решение.

Мы просто подавляем вызовы visit из классов из пакета java.

, используя child.isJavaLibraryMethod(), чтобы проверить, из пакета java.

Если он из пакета java, мы просто не вызываем visit с этим классом, поэтому, добавив эту проверку для родительских и дочерних вызовов и подавив вывод, мы получаем правильный callgraph. (и в качестве бонуса это намного быстрее, поскольку вы больше не пересекаете библиотеку java.

, поэтому код изменяется на:

private static void visit(CallGraph cg, SootMethod method) {
          String identifier = method.getSignature();
          visited.put(method.getSignature(), true);
          dot.drawNode(identifier);
          // iterate over unvisited parents
          Iterator<MethodOrMethodContext> ptargets = new Sources(cg.edgesInto(method));
          if (ptargets != null) {
            while (ptargets.hasNext()) {
                SootMethod parent = (SootMethod) ptargets.next();
                if (!visited.containsKey(parent.getSignature()) && !parent.isJavaLibraryMethod()) visit(cg, parent);
            }
          }
          // iterate over unvisited children
          Iterator<MethodOrMethodContext> ctargets = new Targets(cg.edgesOutOf(method));
          if (ctargets != null) {
            while (ctargets.hasNext()) {
               SootMethod child = (SootMethod) ctargets.next();
               dot.drawEdge(identifier, child.getSignature());
               if (!child.isJavaLibraryMethod())System.out.println(method + " may call " + child);
               if (!visited.containsKey(child.getSignature()) && !child.isJavaLibraryMethod()) visit(cg, child);
            }
          }
    }
...