【问题标题】:Listing all unimplemented methods called from within a method列出从方法中调用的所有未实现的方法
【发布时间】:2015-09-15 20:23:21
【问题描述】:

我们有一个庞大的项目,其中许多方法已预先声明,并且正在进行实施。所有声明的方法都有一个简单地抛出异常的主体,比如 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,但我们不确定如何深入所有级别,因为它似乎为我们提供了从方法内调用的所有方法,但不是递归的。

非常感谢任何帮助:)

【问题讨论】:

  • 是否使用 grep 选项?
  • 这甚至不会编译。正文中不能有throws,它必须是throw new UnimplException(),并在methA() 后面加上throws UnimplExceptionmethA()methB() 也不是静态的,所以你不能这样称呼它们。
  • 从您发布的代码中,尝试编译会使 java 编译器标记每个未实现的方法,因为它们在没有报告的情况下抛出异常(甚至抛出异常;您需要 new 关键字和UnimplException())
  • @Fildor 听起来 OP 要求从某个方法获取调用树的未实现叶子,而不仅仅是其中包含 throw 语句的所有方法的列表。
  • 如果您使用的是 Eclipse,您可以单击 Exception UnimplExceptionCtrl+Shift+G 以显示工作区中对类的所有引用。或者,您可以右键单击 Exception 和 References -> Workspace

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


【解决方案1】:

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

类似:

  1. 使用调用图代码构建所有方法调用的列表。
  2. 将该数据保存在某处。
  3. 递归解析该结构以查找匹配方法。

因此,从您的示例来看,第 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 的方法,而不是那些只抛出异常但不确定是否重要的​​方法。

标准免责声明 - 刚刚输入 - 尚未编译/运行,因此很可能是拼写错误,但希望这个想法有所帮助。

【讨论】:

  • 感谢@Barney!我会试试这个……这个主意听起来不错。 :)
  • @popeye 不用担心 - 希望对您有所帮助。刚刚尝试了代码图的东西,快速浏览一下似乎效果很好。还刚刚更新了递归代码 - 如果在调用异常方法之前检测到代码循环,以前的版本将失败。
猜你喜欢
  • 2021-12-30
  • 1970-01-01
  • 2018-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-30
  • 1970-01-01
  • 2010-09-30
相关资源
最近更新 更多