Skip to content

lucadibello/bytecode-static-call-graph

Repository files navigation

Java Static Call Graph Generator

A static analysis tool that builds class hierarchies and call graphs from Java bytecode. It parses JAR files using the ASM library, identifies all possible call targets for each polymorphic call site via Class Hierarchy Analysis (CHA), and renders the results as DOT graphs for visualization with Graphviz.

Features

  • Class Hierarchy Analysis (CHA): Builds a complete type hierarchy including superclasses, interfaces, and subtypes.
  • Call Graph Construction: Identifies method invocations and resolves virtual/interface calls to all possible runtime targets.
  • Polymorphism Resolution: Uses BFS traversal through the class hierarchy to find all possible implementations of virtual and interface calls.
  • DOT Visualization: Generates Graphviz-compatible .dot files with color-coded edges and styled nodes for classes, methods, and call relationships.

Example: Pac-Man Call Graph

The bundled pacman.jar (in src/test/resources/) contains a simple Pac-Man game with polymorphic classes (Sprite, Pacman, Ghost, World, etc.). Running the analyzer on it produces the following static call graph:

Pac-Man Static Call Graph

What you can see:

  • Class hierarchy: Pacman and Ghost both implement the Sprite interface; MagicWorld and NormalWorld extend the abstract World class.
  • Polymorphic resolution: A call to Sprite.step() fans out to both Pacman.step() and Ghost.step() as possible targets.
  • Edge styles: Dashed edges represent virtual calls, dotted edges represent interface calls, and solid edges represent special calls (constructors, super).

How It Works

  1. JAR Scanning: The ArchiveScanner walks through a JAR file and loads each .class file using ASM's ClassNode.
  2. Hierarchy Construction: The ClassHierarchyBuilder records superclass relationships, implemented interfaces, subtypes, and declared methods for each class.
  3. Call Graph Analysis: The CallGraphClassHierarchyAnalyzer examines bytecode instructions (INVOKEVIRTUAL, INVOKESPECIAL, INVOKEINTERFACE) and resolves possible call targets through the hierarchy.
  4. Rendering: The CallGraphRenderer outputs a DOT graph with:
    • Class nodes styled by kind (solid = concrete, dashed = abstract, dotted = interface)
    • Hierarchy edges (solid arrows to superclasses, dotted to interfaces)
    • Call edges (dashed for virtual, dotted for interface, solid for special) with color coding (blue = declared target, brown = CHA-resolved target)

Usage

Prerequisites

  • Java 21 or higher
  • Graphviz (optional, required for PDF rendering)
  • Gradle (included wrapper)

Quick Start

Run the included example using the bundled Pac-Man JAR:

./run.sh

This will:

  1. Build the project
  2. Analyze src/test/resources/pacman.jar
  3. Generate out/callgraph.dot
  4. Convert to PDF: out/callgraph.pdf (requires Graphviz)

You can also pass a custom JAR file:

./run.sh /path/to/your.jar

Using Gradle

./gradlew run --args "'/path/to/input.jar' '/path/to/output_dir'"

Using the JAR directly

./gradlew build

java -cp build/libs/*.jar:lib/asm-9.7.jar:lib/asm-tree-9.7.jar:lib/asm-util-9.7.jar \
     lab.App /path/to/input.jar /path/to/output_dir

Output

The tool generates a callgraph.dot file in the specified output directory. Convert it to a visual format with Graphviz:

dot -Tpdf -o callgraph.pdf callgraph.dot
dot -Tpng -o callgraph.png callgraph.dot

Visual legend:

Element Meaning
Solid box Concrete class
Dashed box Abstract class
Dotted box Interface
Solid arrow (tan) Extends superclass
Dotted arrow (tan) Implements interface
Blue call edge Declared call target
Brown call edge CHA-resolved possible target

Project Structure

.
├── run.sh                             # Quick-start script
├── build.gradle                       # Gradle build configuration
├── src/
│   ├── main/java/lab/
│   │   ├── App.java                   # Main entry point
│   │   ├── framework/
│   │   │   ├── ArchiveScanner.java    # JAR file traversal
│   │   │   └── ClassAnalyzer.java     # Analysis pass interface
│   │   ├── hierarchy/
│   │   │   ├── ClassHierarchy.java    # Type registry
│   │   │   ├── ClassHierarchyBuilder.java  # Builds hierarchy from bytecode
│   │   │   └── type/                  # Type representations
│   │   └── callgraph/
│   │       ├── CallGraphClassHierarchyAnalyzer.java  # CHA-based call analysis
│   │       ├── CallGraphRenderer.java                # DOT graph generation
│   │       ├── CallSite.java                         # Method invocation model
│   │       └── Method.java                           # Method declaration model
│   └── test/
│       ├── java/lab/
│       │   ├── PacmanCallGraphTest.java        # Call graph tests
│       │   └── PacmanClassHierarchyTest.java   # Hierarchy tests
│       └── resources/
│           └── pacman.jar              # Test JAR (Pac-Man game)
└── gradlew                            # Gradle wrapper

License

This project is open source and available for personal and educational use.

About

Java static call graph generator using Class Hierarchy Analysis (CHA) on bytecode, with Graphviz DOT visualization.

Topics

Resources

Stars

Watchers

Forks

Contributors