【问题标题】:Creating a visual call graph for java projects from command line从命令行为 java 项目创建可视化调用图
【发布时间】:2015-03-20 08:19:44
【问题描述】:

我正在寻找从命令行为 java 项目创建调用图。我探索了几个项目,每次都达不到我的目标(无论是在我的理解上,还是在功能上)。一些关于如何做到这一点的简单指南会很棒,另外一个目的是获得该图的文本表示。

这是我尝试过的:

调用图:https://github.com/gousiosg/java-callgraph

这为我提供了我想要的文本输出,但我找不到方法(在查看文档一段时间后)将其转换为可视(图像文件)图形输出。

烟灰:http://sable.github.io/soot/

在花费大量时间查看似乎很难理解的 SOOT 文档之后,我设法让 SOOT 创建字节码。但是,我找不到任何关于如何从中创建调用图的指南。我只在主页上看到它可以 这样做,并且我从我的谷歌搜索中收到了几个电子邮件对话,所有这些都只是没有答案的问题。我正在使用命令的夜间构建:

java -cp soot-trunk.jar soot.Main -cp . -pp HelloWorld

HelloWorld 是我的 java 文件的名称,我得到一个 .class 文件的输出,但我看不到如何获取实际的调用图。这是在遵循此处的指南之后:https://github.com/Sable/soot/wiki/Running-Soot。当我关注有关可视化的链接时,它们似乎是断开的链接,然后重定向回主页。我可以在命令行页面上看到一些关于使用 -cg 标志的信息,但是什么都不能工作——我只是得到一个选项解析错误,提示一个无效的参数:https://ssebuild.cased.de/nightly/soot/doc/soot_options.htm#phase_5

搜索 stackoverflow - 现有答案 我已经看过几个类似的问题,例如:Static analysis of Java call graph 但是,答案只是说“使用烟灰”或“使用调用图”,我一直在尝试这些没有任何运气 - 尽管我与调用图最接近,因为我确实有文本输出。

我看到一些基于 GUI 的软件和 Eclipse 插件声称可以创建调用图,但我正试图通过命令行使其工作。

非常感谢任何帮助、指南或带有调用图或 Soot 的命令集,或者其他程序会真正提供帮助。可能还值得向他们提交任何简短的教程以获取他们的文档,因为似乎有搜索时问题多于答案。

作为参考,我目前正在尝试以下一个非常简单的类:

public class HelloWorld {

    public static void main(String[] args) {
        foo();
    }
    public static void foo(){
        System.out.println("Hello World");
    }
}

【问题讨论】:

    标签: java static-code-analysis call-graph


    【解决方案1】:

    看起来调用图确实产生了相当不错的输出。让我们做一个快速的 PoC。

    我将使用调用图开发人员提供的示例输出。

    org.apache.batik.dom.AbstractParentNode:appendChild org.apache.batik.dom.AbstractParentNode:fireDOMNodeInsertedEvent 6270 org.apache.batik.dom.AbstractParentNode:fireDOMNodeInsertedEvent org.apache.batik.dom.AbstractDocument:getEventsEnabled 6280 org.apache.batik.dom.AbstractParentNode:checkAndRemove org.apache.batik.dom.AbstractNode:getOwnerDocument 6280 org.apache.batik.dom.util.DoublyIndexedTable:put org.apache.batik.dom.util.DoublyIndexedTable$Entry:DoublyIndexedTable$Entry 6682 org.apache.batik.dom.util.DoublyIndexedTable:put org.apache.batik.dom.util.DoublyIndexedTable:hashCode 6693 org.apache.batik.dom.AbstractElement:invalidateElementsByTagName org.apache.batik.dom.AbstractElement:getNodeType 7198 org.apache.batik.dom.AbstractElement:invalidateElementsByTagName org.apache.batik.dom.AbstractDocument:getElementsByTagName 14396 org.apache.batik.dom.AbstractElement:invalidateElementsByTagName org.apache.batik.dom.AbstractDocument:getElementsByTagNameNS 28792

    有几种可用的图形渲染引擎。最简单的可能是DOT(请查看链接,列出了其他几个不错的工具)。

    为了使用DOT,我需要稍微转换一下数据。假设我想保留 ClassName:methodName 并跳过包。

    超级简单,你可以用任何工具来做,但我会用sed

    OUT=callgraph.dot 回声“图形测试{”> $OUT sed -E 's/[a-z]+\.//g; s/[0-9]+\/;/; s/ / -- /; s/[\$|\:]/_/g' callgraph.txt >> $OUT 回声“}”>> $OUT dot -Tpng callgraph.dot -o callgraph.png

    这是生成的结果:

    图测试{ AbstractParentNode_appendChild -- AbstractParentNode_fireDOMNodeInsertedEvent ; AbstractParentNode_fireDOMNodeInsertedEvent -- AbstractDocument_getEventsEnabled ; AbstractParentNode_checkAndRemove -- AbstractNode_getOwnerDocument ; DoublyIndexedTable_put -- DoublyIndexedTable_Entry_DoublyIndexedTable_Entry ; DoublyIndexedTable_put -- DoublyIndexedTable_hashCode ; AbstractElement_invalidateElementsByTagName -- AbstractElement_getNodeType ; AbstractElement_invalidateElementsByTagName -- AbstractDocument_getElementsByTagName ; AbstractElement_invalidateElementsByTagName -- AbstractDocument_getElementsByTagNameNS ; }

    DOT 非常友好地将其呈现为以下内容:

    所有图表均从初始数据中提取:

    请注意,您可以根据需要调整渲染。 DOTgraphviz 的一部分,graphviz 是一组非常灵活的工具。

    我的回答背后有一个总体思路:

    • 使用任何合适的工具来生成跟踪
    • 找到一个好的渲染解决方案
    • 花一些时间来获得简单的自动转换

    顺便说一句,看看canviz

    Canviz 是一个 JavaScript 库,用于将 Graphviz 图形绘制到网络上 浏览器画布。从技术上讲,Canviz 是一个 JavaScript xdot 渲染器。它适用于大多数现代浏览器。

    编码愉快:)

    【讨论】:

    • 谢谢!虽然我还没有时间尝试这个,但它看起来正是我所追求的。毫无疑问,这个答案也将帮助未来查看这个问题的人,因为它得到了很好的解释。非常感谢。
    【解决方案2】:

    还有 WALA:http://wala.sourceforge.net/wiki/index.php/Main_Page

    它支持多种调用图构建策略,并且已经与 DOT 集成。如果您遵循入门指南,它们已经包含许多直观地显示调用图的示例程序。他们的用户列表也很支持。

    这里他们提到了一个显示调用图的示例:

    http://wala.sourceforge.net/wiki/index.php/UserGuide:Getting_Started#Other_basic_examples

    【讨论】:

      【解决方案3】:

      这是一个老问题,但我还没有找到一个好的工具。所以按照这个线程的建议,我创建了java-call-graph-plotter。它使用 java-call-graph 和 VisJs 来做到这一点。 您可以按照以下步骤操作:

      克隆 repo 并进入项目文件夹:

      git clone https://github.com/marcello-dev/java-call-graph-plotter.git

      cd java-call-graph-plotter

      创建调用图:

      java -jar javacg/javacg-0.1-SNAPSHOT-static.jar target-jar/demo-customer-0.0.1-SNAPSHOT.jar > call-graph.txt

      为 Python 3 创建一个虚拟环境:

      python3 -m venv venv

      激活它:

      source venv/bin/activate

      安装依赖:

      pip install -r requirements.txt

      绘制图表:

      python callgraphplotter.py call-graph.txt ApiDBSelector

      将在输出文件夹中生成一个名为 call-graph.html 的文件。您可以在浏览器中打开它。希望对你有帮助!更多信息here

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-12-25
        • 1970-01-01
        • 1970-01-01
        • 2010-09-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-11
        相关资源
        最近更新 更多