Creating a visual call graph for java projects from command line

It's an old question but I still haven't found a good tool. So following the suggestion on this thread I created java-call-graph-plotter. It uses java-call-graph and VisJs to do that. You can follow these steps:

Clone the repo and get into the project folder:

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

cd java-call-graph-plotter

Create the call graph:

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

Create a virual environment for Python 3:

python3 -m venv venv

Activate it:

source venv/bin/activate

Install the dependencies:

pip install -r requirements.txt

Plot the graph:

python callgraphplotter.py call-graph.txt ApiDBSelector

A file called call-graph.html will be generated in the output folder. You can open it in your browser. I hope you find it useful! More info here


There's also WALA: http://wala.sourceforge.net/wiki/index.php/Main_Page

It supports several call graph building strategies and already has integration with DOT. If you follow th getting started guide, they already contain a number of example programs that display call graph visually. Their user list is also quite supportive.

Here they mention an example that displays the call graph:

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


It does look like Call Graph produces quite a decent output. Let's do a quick PoC.

I'll use a sample output provided by Call Graph developer.

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

There are several graph rendering engines available. The simplest possible is DOT (please check the link, there are several other good tools listed).

In order to use DOT I'll need to transform data a bit. Let's say I would like to keep ClassName:methodName and skip package.

It is super easy, you can use any tool to do that, but I'll use 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

Here is generated result:

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 was pretty kind to render that into the following:

enter image description here

All graphs were extracted from the initial data:

enter image description here

Please note, you can tune rendering as you want. DOT is a part of graphviz which is quite a flexible set of tools.

There is a general idea behind my answer:

  • use any suitable tool to generate trace
  • find a good rendering solution
  • spend some time in order to get simple automated conversion

BTW, take a look at canviz

Canviz is a JavaScript library for drawing Graphviz graphs to a web browser canvas. More technically, Canviz is a JavaScript xdot renderer. It works in most modern browsers.

Happy coding :)