Java 列出从方法中调用的所有未实现的方法

Java 列出从方法中调用的所有未实现的方法,java,recursion,bytecode,java-bytecode-asm,javassist,Java,Recursion,Bytecode,Java Bytecode Asm,Javassist,我们有一个巨大的项目,其中许多方法已经预先声明,并且正在进行实现。所有声明的方法都有一个只抛出异常的主体,比如unflexception。 现在,由于已经声明了这些方法,并且提供了一个有效的(可编译的)主体,因此可以从其他方法中调用它们 现在的问题是,如果给定一个特定的方法,有没有办法列出所有这些未实现的(只有一个可编译的体抛出一个特定的异常)方法 为了进一步说明(代码是为了传达想法,而不是严格地对编译器友好): 所以,如果我们从methC开始,那么我们想沿着方法树一直走到methA,因为met

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

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

为了进一步说明(代码是为了传达想法,而不是严格地对编译器友好):

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

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


非常感谢您的帮助:)

您看过这个项目吗:?这似乎完成了Java内省部分,列出了jar文件中每个方法的每个方法调用。我会尝试使用它来解析代码,然后递归结果

比如:

  • 使用callgraph代码构建所有方法调用的列表
  • 把数据保存在某个地方
  • 递归地解析该结构以找到匹配的方法
  • 因此,根据您的示例,步骤1将给出如下内容:

    A:methA -> UnimplException:<init>
    B:methB -> A:methA
    C:methC -> B:methB
    
    A:methA->unflexception:
    甲氧基甲烷
    C:methC->B:methB
    
    然后将它们放入a中,并执行相当简单的递归搜索:

    // 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;
    }
    
    //这是从调用图代码的输出填充的
    com.google.common.collect.Multimap methodMap;
    void checkAllMethods(){
    for(字符串方法:methodMap.keySet()){
    List callStack=new ArrayList();
    if(doesMethodThrowUnflexception(方法,调用堆栈)){
    系统输出打印LN(方法);
    //如果有兴趣,也可以打印callStack
    }
    }
    }  
    布尔DoesMethodThrowUnflexception(字符串方法,列表调用堆栈){
    for(字符串子项:methodMap.get(方法)){
    //必须检查callgraph中的确切方法名称
    if(child.equals(“unflexception:)){
    返回true;
    }
    //如果尚未看到,则递归到子级
    如果(!callStack.contains(子)){
    callStack.add(子级);
    if(doesMethodThrowUnflexception(子级,调用堆栈)){
    返回true;
    }
    callStack.remove(callStack.size()-1);
    }
    }
    返回false;
    }
    
    不能严格满足您的要求,因为这将报告任何抛出
    unflexception
    的方法,而不是那些只抛出异常,但不确定这是否重要的方法


    标准免责声明-只是输入了这个-还没有编译/运行它,所以可能是打字错误,但希望这个想法有帮助。

    使用grep是一个选项吗?这甚至不会编译。您不能将
    抛出
    放在正文中,它必须是
    抛出新的unflexception()
    ,并将
    抛出unflexception
    放在
    methA()之后
    methA()
    methB()
    也不是静态的,所以不能这样调用它们。从您发布的代码中,尝试编译会使java编译器标记每个未实现的方法,因为它们在不报告异常的情况下抛出异常(或者甚至正确抛出异常;您需要新关键字和
    Unplexception()
    )@Fildor听起来OP要求调用树的未实现叶子从某个方法中生根,不仅仅是包含throw语句的所有方法的列表。如果使用Eclipse,可以单击Exception
    unflexception
    Ctrl+Shift+G
    来显示工作区中对类的所有引用。或者,您可以右键单击异常并
    References->Workspace
    谢谢@Barney!我来试试……这个主意听起来不错。:)@大力水手不用担心,希望它能帮上忙。刚刚试过代码图的东西,快速看一下似乎效果不错。另外,刚刚更新了递归代码-如果在调用异常方法之前检测到代码循环,则以前的版本将失败。
    // 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;
    }