Static analysis of Java call graph

29.8k views Asked by At

What I'd like to do is scan a set of Java classes, and trace all method calls from a specific method of an Abstract Class, and within that context, build a list of all code which performs some operation (in this case, instantiates an instance of a certain class). I want to know, the line number, and the arguments supplied.

I've begun looking at BCEL, but it doesn't seem to have call graph tracing built in? I'm hesitant to write my own because getting the overloading, type signatures and polymorphic dispatch right might be be tricky.

I half expected a tool or example code to exist, but I haven't found anything yet. It really feels like I'm about to reinvent a wheel. But if I do it will be an open source wheel and available on GitHub ;-)

PS: You will find the existing question "How to Generator a Java Call Graph", because it sounds identical, but it's not at all what I need.

8

There are 8 answers

0
metdos On

You can use Doxygen with Graphviz. It is easy to install and use.

0
Georgios Gousios On

You can use the java-callgraph tool suite to create accurate enough static and dynamic callgraphs for Java.

0
James from CppDepend Team On

You can try JavaDepend , it gives many features needed for dependencies and metrics, it provides also a CQL like SQL to request your code base.

Disclosure: it's a commercial software.

0
Adrninistrator On

You can see: https://github.com/Adrninistrator/java-all-call-graph/blob/main/README-en.md

The output example:

  • upward
org.mybatis.spring.SqlSessionUtils:lambda$closeSqlSession$6(org.apache.ibatis.session.SqlSession)
[0]#org.mybatis.spring.SqlSessionUtils:lambda$closeSqlSession$6(org.apache.ibatis.session.SqlSession)
[1]#  org.mybatis.spring.SqlSessionUtils:closeSqlSession(org.apache.ibatis.session.SqlSession,org.apache.ibatis.session.SqlSessionFactory)
[2]#    org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor:invoke(java.lang.Object,java.lang.reflect.Method,java.lang.Object[])    !entry!

org.mybatis.spring.SqlSessionUtils:lambda$getSqlSession$0()
[0]#org.mybatis.spring.SqlSessionUtils:lambda$getSqlSession$0()
[1]#  org.mybatis.spring.SqlSessionUtils:getSqlSession(org.apache.ibatis.session.SqlSessionFactory) !entry!
[1]#  org.mybatis.spring.SqlSessionUtils:getSqlSession(org.apache.ibatis.session.SqlSessionFactory,org.apache.ibatis.session.ExecutorType,org.springframework.dao.support.PersistenceExceptionTranslator)
[2]#    org.mybatis.spring.SqlSessionUtils:getSqlSession(org.apache.ibatis.session.SqlSessionFactory)   !entry!
[2]#    org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor:invoke(java.lang.Object,java.lang.reflect.Method,java.lang.Object[])    !entry!
  • downward
org.mybatis.spring.SqlSessionFactoryBean:scanClasses(java.lang.String,java.lang.Class)
[0]#org.mybatis.spring.SqlSessionFactoryBean:scanClasses(java.lang.String,java.lang.Class)
[1]#  org.springframework.util.StringUtils:tokenizeToStringArray(java.lang.String,java.lang.String)
[1]#  org.springframework.util.ClassUtils:convertClassNameToResourcePath(java.lang.String)
[1]#  org.springframework.core.io.support.ResourcePatternResolver:getResources(java.lang.String)
[1]#  org.springframework.core.type.classreading.MetadataReaderFactory:getMetadataReader(org.springframework.core.io.Resource)
[1]#  org.springframework.core.type.classreading.MetadataReader:getClassMetadata()
[1]#  org.springframework.core.type.ClassMetadata:getClassName()
[1]#  org.apache.ibatis.io.Resources:classForName(java.lang.String)
[2]#    org.apache.ibatis.io.ClassLoaderWrapper:classForName(java.lang.String)
[3]#      org.apache.ibatis.io.ClassLoaderWrapper:getClassLoaders(java.lang.ClassLoader)
[3]#      org.apache.ibatis.io.ClassLoaderWrapper:classForName(java.lang.String,java.lang.ClassLoader[])
[1]#  org.mybatis.spring.SqlSessionFactoryBean:lambda$scanClasses$19(org.springframework.core.io.Resource,java.lang.Throwable)
0
Ira Baxter On

It sounds like you want something that provides access to the abstract syntax and a complete symbol table. Then a custom scan of the ASTs of the functions in the call graph rooted in each implementing method (as indicated by the symbol tables) of an abstract method gives you a chance to locate a new operation whose type is the specific class of interest.

The DMS Software Reengineering Toolkit is generalized compiler technology providing basic services of parsing, AST building/navigation, symbol table building/navigation, control flow, data flow and call graph construction. DMS has an optional Java Front End that provides a full Java parser, builds Java ASTs and symbol tables, and can construct a call graph. The Java Front End can also read .class files; you weren't clear as to whether you wanted to climb into class files, too, hunting for information.

The answer you want isn't off the shelf. You need to build some custom code to implement the ideas in the first paragraph, but DMS can provide most of the raw material. It doesn't provide much detail from the .class files (these are used mostly to resolve types in source code).

1
Eric On

Soot should allow you to easily achieve what you are looking for: http://www.sable.mcgill.ca/soot/

It can construct precise call graphs fully automatically.

You can find all necessary documentation here: http://www.sable.mcgill.ca/soot/tutorial/index.html

Also, there's an active mailing list for Soot.

0
Christophe Roussy On

For a 'recent' Eclipse install (relative to the question), see Certiv CallGraph.

CallGraph enables graphical analysis of program call relations and flow sequencing. Also enables exploration of extended class inheritance hierarchies.

Call-path analysis and class hieararchy resolution are performed using the JDT platform Search and Call Hierarchy mechanisms.

Sequence diagrams are generated from a static analysis of of the JDT platform AST for any selected class or method.

Uses Zest as the graphics visualization engine.

You can install it via the Eclipse marketplace. I am not involved in making this. You cannot zoom out which is not very practical but has support for Sequence Diagram which is nice and allows to open/close nodes on demand to dig further.

Requirements:

Eclipse 4.6 (Neon) on Java 8 VM
Eclipse Zest Visualization Toolkit 1.7

Eclipse Public License v1.0

0
Gajanand Jha On

A Wonderful git repo is here for this:

https://github.com/gajanandjha/Java-Call-Tree-Generator

It generates a call tree of all threads in a Java process, then the repo README comments gives us some Unix magic commands to get the thread traces that we require and generates a simple webpage with tree view of all the methods the thread has visited in a flow.