从命令行为 Java 项目创建可视化调用图

2022-09-01 21:20:11

我希望从命令行为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

搜索堆栈溢出 - 现有答案我已经看过几个类似的问题,例如:Java调用图的静态分析 但是,答案只是说“使用烟灰”或“使用调用图”,我一直在尝试这些没有任何运气 - 尽管我最接近调用图,因为我有文本输出。

我看到一些基于GUI的软件和eclipse插件声称可以创建调用图,但我试图从命令行进行此操作。

任何帮助都是非常值得赞赏的,一个指南,或者一组带有调用图或Sot的命令,或者其他程序,都会真正有所帮助。可能还值得向他们提交任何简短的教程,以便他们的文档,因为在搜索时似乎有更多的问题而不是答案。

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

public class HelloWorld {

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

答案 1

看起来Call Graph确实产生了相当不错的输出。让我们做一个快速的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(请检查链接,还有其他几个好的工具列出)。

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

这非常简单,您可以使用任何工具来执行此操作,但是我将使用:sed

OUT=callgraph.dot
echo "graph test {" > $OUT
sed -E 's/[a-z]+\.//g; s/[0-9]+\/;/; s/ / -- /; s/[\$|\:]/_/g'  callgraph.txt >> $OUT
echo "}" >> $OUT
dot -Tpng callgraph.dot -o callgraph.png

以下是生成的结果:

graph test {
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非常友善地将其呈现为以下内容:

enter image description here

所有图形都是从初始数据中提取的:

enter image description here

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

我的答案背后有一个大概的想法:

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

顺便说一句,看看坎维兹

Canviz是一个JavaScript库,用于将Graphviz图形绘制到Web浏览器画布上。从技术上讲,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


推荐