列出从方法

时间:2015-09-15 20:23:21

标签: java recursion bytecode java-bytecode-asm javassist

我们有一个庞大的项目,其中已经预先声明了许多方法,并且实现正在进行中。所有声明的方法都有一个简单抛出异常的主体,比如UnimplException。 现在,由于已经声明了方法并且提供了一个有效的(可编译的)主体,因此可以从其他方法中调用它们。

现在的问题是,有没有办法列出所有这些未实现的(只有一个可编辑的机构抛出特定的异常)给定特定方法的方法?

为了说明更多(代码是传达这个想法,而不是严格的编译器友好):

class A {
    methA () {
        throw new UnimplException();
    }
}

class B {
    methB () {
        // proper body
        // and calls methA
        A.methA();
        // does something else
        // and returns.
    }
}

class C {
    methC () {
        // proper body
        // calls methB
        B.methB();
    }
}

所以,如果我们从例如methC开始,那么我们希望沿着方法树一直走到达到methA,因为methC调用methB(这是正确实现的,我们不感兴趣),这反过来调用methA没有正确实施,这是我们想要找到的。 我们希望从一个方法开始搜索所有这些未实现的方法,并深入到几个层次,直到我们覆盖所有这些未实现的方法。

我们想到了JavaAssist,但我们不确定如何降低所有级别,因为它似乎在给我们所有从方法中调用但不是递归的方法。

非常感谢任何帮助:)

1 个答案:

答案 0 :(得分:2)

你见过这个项目:https://github.com/gousiosg/java-callgraph?这似乎是Java内省部分,列出了jar文件中每个方法的每个方法调用。我尝试使用它来解析代码,然后只是递归结果。

类似的东西:

  1. 使用callgraph代码构建所有方法调用的列表。
  2. 将数据保存在某处。
  3. 递归地解析该结构以找到匹配的方法。
  4. 因此,从您的示例中,第1步将提供如下内容:

    A:methA -> UnimplException:<init>
    B:methB -> A:methA
    C:methC -> B:methB
    

    然后推送Multimap中的那些并进行相当简单的递归搜索:

    // this is populated from the output of the callgraph code
    com.google.common.collect.Multimap<String, String> methodMap;
    
    void checkAllMethods() {
      for (String method : methodMap.keySet()) {
        List<String> callStack = new ArrayList<>();
        if (doesMethodThrowUnimplException(method, callStack)) {
          System.out.println(method);
          // can print callStack too if interested
        }
      }
    }  
    
    boolean doesMethodThrowUnimplException(String method, List<String> callStack) {
      for (String child : methodMap.get(method)) {
        // have to check the exact method name from callgraph
        if (child.equals("UnimplException:<init>")) {
          return true;
        }
        // recurse into child if not already seen
        if (!callStack.contains(child)) {
          callStack.add(child);
          if (doesMethodThrowUnimplException(child, callStack)) {
            return true;
          }
          callStack.remove(callStack.size() - 1);
        }
      }
      return false;
    }
    

    没有严格满足您的要求,因为这将报告任何抛出UnimplException的方法,而不是那些只抛出异常的方法,但不确定是否重要。

    标准免责声明 - 只需键入此内容即可编译/运行它,因此很可能是拼写错误,但希望这个想法有所帮助。