2

我必须重构和维护一堆看起来很糟糕的 Java 类。许多具有以下实现模式

class Machine {
    public int advance(int state) {
        switch(state) {
        case 7:  return step_7();
        case 13: return step_13();
        case 4:  return step_4();
        }
    }
    private int step_7() {
        if(something) return 13; else return 4;
    }
    private int step_13() {
        ...
        return 4;
    }
    private int step_4() {
        if(miep) return 7;
        ...
        return 13;
    }
}

从这里我想生成一个图(使用 Graphviz 和dot)——有点像“静态调用图”,但不完全是。

除了使用 Perl 或 Python 自己解析 Java 代码之外,我在这里玩游戏如何自动执行此操作。

我真正想要的是拥有一个抽象语法树(AST)或类似的东西,我可以浏览并同时打印dot-code。

  • 如何在这里生成可遍历的 AST?我想遍历将在 Java 中完成,但如果输出是任何文本表示形式,那就没问题(gprof想到这里)。
  • 任何其他方法,不使用 AST?也许我只是个盲人,有一种更好、更简单的方法可以做到这一点。
4

1 回答 1

6

周围有多种 Java 解析器可以生成 AST:

但是在处理真正的计算机语言时,AST 是远远不够的。例如,要确定调用站点可能调用的方法,您需要全名和类型解析,以便您可以准确地确定源文件中的数千个foo中的哪个 foo可能被调用。由于其复杂的查找规则,这对于 Java 来说并不容易计算。有关此主题的更多详细信息,请参阅我关于解析后的生活的文章。除非您不关心答案的准确性,否则您不太可能仅通过使用 Python 或 Perl 来轻松复制这些功能。Eclipse JDT 可能有名称解析;我不知道。ANTLR Java 解析器没有;他们只是解析。

DMS 的 Java 前端具有 Java 的全名和类型解析。要静态确定您的调用图,您基本上需要一个指向分析;每个包含任何类型对象的字段本质上都是一个指针,您想知道每个指针,特别是它可能选择哪些对象,然后您需要构造一个(全局)调用图来获取您想要的基本信息。DMS 为计算各种控制和数据流分析提供支持; Java 前端提供基本的流事实,它将计算本地数据流分析。要获得指向分析,您必须在 DMS 的帮助下组装这些事实,然后构建该调用图。我们还没有为 Java 使用 DMS,但我们为 C 大规​​模使用(一个系统中有 2600 万行),Java 的类似物将非常相似,并使用大多数相同的 DMS 机制;一旦您进行了指向分析,调用图的构建就相当容易了。我们已将此类图导出为 DOT 图;您需要过滤它们以获得 DOT 实际负担得起的子图。

您可能能够从类二进制分析文件(例如Wala )中收集流分析事实。您仍将面临构建指向分析和全局调用图的问题。我记得瓦拉在这里有某种帮助,但我不记得是什么。

您也许可以使用分析器工具收集动态构建的调用图。除非您在分析过程中仔细运用所有系统功能,否则这样的调用图可能非常不完整;这很难做到。

最终,您可能想要更改您的代码。也许你想内联你的stepN函数。也许你想手工完成,但如果你的代码充满了这样的东西,也许你想要自动化。在这里,像 DMS 这样的工具提供了源到源的转换,从而实现了这种自动代码更改。瓦拉在这里帮不了你。

于 2012-06-12T11:52:30.497 回答