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

The*_*son 19 java call-graph static-code-analysis

我想从命令行为java项目创建一个调用图.我已经探索了几个项目,每次都达不到我想要的目标(无论是我的理解还是功能).关于如何做到这一点的一些简单指南将是很好的,另一个目标是获得该图的文本表示.

这是我尝试过的:

呼叫图:https://github.com/gousiosg/java-callgraph

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

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

花了很多时间查看SOOT文档,这似乎很难遵循,我设法让SOOT创建字节码.但是,我找不到有关如何从中创建调用图的任何指南.我只在主页上看到它可以执行此操作,我从谷歌搜索中获得了几个电子邮件对话,所有这些只是没有答案的问题.我正在使用命令的每晚构建:

java -cp soot-trunk.jar soot.Main -cp . -pp HelloWorld
Run Code Online (Sandbox Code Playgroud)

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 - 现有答案 我已经看过几个类似的问题,例如:Java调用图的静态分析 然而,答案只是说"使用soot",或"使用call-graph",我一直在尝试这些没有任何运气 - 虽然我最接近调用图,因为我有文本输出.

我看到一些基于GUI的软件和eclipse插件声称可以创建调用图,但我试图从命令行开始工作.

任何帮助真的很感激,一个指南,或一组命令与调用图或Soot,或其他程序真的会有所帮助.可能值得为他们的文档提交任何简短的教程,因为似乎有更多的问题而不是搜索时的答案.

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

public class HelloWorld {

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

Ren*_*nov 13

它看起来像Call Graph产生相当不错的输出.我们来做一个快速的PoC吧.

我将使用Call Graph开发人员提供的示例输出.

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
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 非常友好地将其呈现在以下内容中:

在此输入图像描述

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

在此输入图像描述

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

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

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

顺便说一句,看一看 canviz

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

快乐编码:)