opal icon indicating copy to clipboard operation
opal copied to clipboard

Help Needed: Generating Call Graph for a JAR File (Including Library and Java Core Calls)

Open jayvishaalj opened this issue 10 months ago • 4 comments

Hi OPAL Team,

I’m new to OPAL and Scala, and I’m trying to generate a call graph for a given JAR file that includes: The chain of library calls (dependencies) Calls to Java core libraries (JDK methods)

I’ve gone through the OPAL documentation and the GitHub repository, but I’m having trouble finding a working example or a step-by-step guide on how to generate a call graph.

What I’ve Tried

I’ve attempted to use the following code (based on the documentation and examples I found):

import org.opalj.br._
import org.opalj.br.analyses._
import org.opalj.br.cg._

object CallGraphExample {
  def main(args: Array[String]): Unit = {
    val project = Project(java.io.File("my-app.jar"))
    val cg = CallGraphFactory.create(project)
    // How do I extract and visualize the call graph?
  }
}
import org.opalj.br.analyses.Project
import org.opalj.tac.cg.CallGraphKey

import java.io.File

object CallGraphApp {

  def main(args: Array[String]): Unit = {

    // Load the JAR file
    val jarPath = "my-jar.jar" // Path to the JAR file
    val project = Project(new File(jarPath))
    // Compute the call graph
    val callGraph = project.get(CallGraphKey)

    // Print the call graph details
    println(s"Call graph contains ${callGraph.numEdges} calls.")
  }
//  callGraph.foreachCallingMethod{ (method, targets) =>
//    println(s"Method $method calls :")
//    targets.foreach(target => println(s" - $target"))
//
//  }
}

However, I’m getting errors, and I’m not sure how to proceed.

Questions

  1. Could you please provide a minimal working example of how to generate a call graph for a JAR file?
  2. How can I include library dependencies and Java core library calls in the call graph?
  3. Are there any demo projects or tutorials available for beginners?
  4. What is the recommended way to visualize the call graph (e.g., DOT format, HTML, etc.)?

Additional Context

Goal: Build a tool to analyze the call chain of a Java project, including its dependencies and JDK calls. Environment: Scala 2.13 OPAL 5.0.0 JDK 17

What I’m Looking For

An example of how to:

  1. Load a JAR file and its dependencies.
  2. Generate a call graph.
  3. Export the call graph for visualization.
  4. Any references or documentation that explains the process step-by-step.

Thank you so much for your help! I’m excited to learn more about OPAL and contribute.

jayvishaalj avatar Feb 03 '25 01:02 jayvishaalj

Please have a look at https://github.com/opalj/opal/blob/develop/DEVELOPING_OPAL/tools/src/main/scala/org/opalj/support/info/CallGraph.scala This might already be able to do what you want or at least show you how call graphs are generated with OPAL now.

You're first example is outdated, there is no CallGraphFactory anymore. The second one looks almost correct, but you cannot use CallGraphKey, but must pick a specific subclass, e.g., RTACallGraphKey. To load the dependencies with your jar, there's multiple ways, the easiest might be, in the creation of the Project, to specifiy not the jar file but the directory in which it and its dependencies reside (given a directory OPAL will analyze all jar, class, and jmod files in the directory and any subdirectories). Other options include not specifying a single file, but an Array[File]. There are also variants of this where you can split this between the code to be analyzed and 'libraryFiles' that are made known to OPAL but not analyzed.

OPAL has no built-in ways to visualize call graphs. You can export a call graph to a JSON format using CallGraphSerializer.writeCG(cg, new File(cgFile.get)) (the CallGraph tool mentioned above can do this for you if specify the -writeCG=file command line argument). You could then process this JSON format to produce DOT, HTML, etc. yourself. There is also this project: https://github.com/MartinKem/Call-Graph-Exploration If you get that and open its index.html in a browser, you can drop a JSON-exported call graph and then use the page to explore it interactively.

errt avatar Feb 03 '25 10:02 errt

Thank you for the detailed explanation and references!

I tried your suggestions, and they worked perfectly! Loading dependencies as a directory and using RTACallGraphKey did the trick. Also, exporting the call graph to JSON was super helpful.

Thank you so much again for your help—I really appreciate it!

jayvishaalj avatar Feb 06 '25 17:02 jayvishaalj

Hi OPAL Team,

Thank you so much for your previous help—it really clarified a lot of my doubts!

I was able to generate the call graph successfully with your suggestions. However, I'm still facing difficulties in generating the call graph only for the actual code in the JAR file without including the chain of library dependencies or JDK calls.

Could you please guide me on how to generate the call graph solely for the application's own code while excluding external libraries? Any steps or code examples would be greatly appreciated.

Thank you once again for your continued support!

jayvishaalj avatar Mar 04 '25 04:03 jayvishaalj

If you want to exclude libraries, just don't include them when instantiating your Project. You can also supply them as the second parameter to Project to have OPAL load the method signatures but not the code. Is that what you are looking for?

errt avatar Mar 04 '25 08:03 errt