Analyzing Method Calls to a Specific Package in a Spring WAR File

When working with a large Spring Boot project, you might need to analyze how classes from a specific package (e.g., com.anonymous.targetpackage) are referenced within the application. A practical use case includes tracking dependencies, debugging, or performing code audits.

This article demonstrates how to achieve this using Java ASM (Abstract Syntax Manipulation) library, which allows us to analyze compiled .class files directly from a WAR file.


Why Use Java ASM for This Task?

Unlike source code analysis, ASM inspects bytecode, making it more accurate for finding method calls, including:

  • Calls from dynamically loaded classes
  • Spring-managed beans and proxies
  • Reflection-based method invocations

This method is faster and more precise than static analysis tools like grep or regex-based scanning.


Setting Up the Project

1. Add ASM Dependencies in pom.xml

First, ensure your Maven project includes ASM dependencies:

<dependencies>
    <dependency>
        <groupId>org.ow2.asm</groupId>
        <artifactId>asm</artifactId>
        <version>9.6</version>
    </dependency>
    <dependency>
        <groupId>org.ow2.asm</groupId>
        <artifactId>asm-commons</artifactId>
        <version>9.6</version>
    </dependency>
</dependencies>

Implementing the WAR File Scanner

The following Java program scans a WAR file and extracts method calls to classes in com.anonymous.targetpackage.

2. Create the WarMethodCallAnalyzer.java File

import org.objectweb.asm.*;
import java.io.IOException;
import java.nio.file.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class WarMethodCallAnalyzer {
    private static final String TARGET_PACKAGE = "com/elgo/ocpp";
    private static final String WAR_FILE_PATH = "target/myapp.war"; // Change to your WAR file path

    public static void main(String[] args) throws IOException {
        List<String> results = new ArrayList<>();

        try (ZipFile warFile = new ZipFile(WAR_FILE_PATH)) {
            Enumeration<? extends ZipEntry> entries = warFile.entries();

            while (entries.hasMoreElements()) {
                ZipEntry entry = entries.nextElement();

                if (entry.getName().startsWith("WEB-INF/classes/") && entry.getName().endsWith(".class")) {
                    analyzeClassFile(warFile, entry, results);
                }
            }
        }

        System.out.println("Class,Method,Calls");
        results.forEach(System.out::println);
    }

    private static void analyzeClassFile(ZipFile warFile, ZipEntry entry, List<String> results) {
        try {
            ClassReader reader = new ClassReader(warFile.getInputStream(entry));
            reader.accept(new ClassVisitor(Opcodes.ASM9) {
                String className;

                @Override
                public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
                    className = name.replace('/', '.');
                }

                @Override
                public MethodVisitor visitMethod(int access, String methodName, String descriptor, String signature, String[] exceptions) {
                    return new MethodVisitor(Opcodes.ASM9) {
                        @Override
                        public void visitMethodInsn(int opcode, String owner, String name, String descriptor, boolean isInterface) {
                            if (owner.startsWith(TARGET_PACKAGE)) {
                                results.add(className + "," + methodName + "," + owner.replace('/', '.') + "." + name);
                            }
                        }
                    };
                }
            }, 0);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Packaging the Project as an Executable JAR

By default, Maven creates a thin JAR, meaning dependencies (like ASM) are not included. To fix this, we create a fat JAR.

3. Update pom.xml to Use maven-shade-plugin

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.3.0</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>com.anonymous.WarMethodCallAnalyzer</mainClass>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Replace com.anonymous.WarMethodCallAnalyzer with your actual package and class name.


Running the Scanner

4. Compile and Build the JAR

Run the following command to generate the fat JAR:

mvn clean package

5. Run the Scanner on a WAR File

java -jar target/WarMethodCallAnalyzer-1.0-SNAPSHOT.jar

Expected Output (CSV Format)

Class,Method,Calls
com.anonymous.Controller,handleRequest,com.anonymous.targetpackage.OcppHandler.processRequest
com.anonymous.ServiceImpl,executeTask,com.anonymous.targetpackage.CommandSender.sendCommand

This output helps you identify all method calls made to com.anonymous.targetpackage from your application.


Conclusion

By leveraging Java ASM, we efficiently analyzed method calls in a Spring Boot WAR file without modifying source code. This approach is invaluable for: ✅ Code Audits – Track dependencies and analyze method calls. ✅ Debugging – Identify runtime dependencies and interactions. ✅ Refactoring – Ensure proper modularization before code changes.

This technique can be further extended to scan JARs inside WEB-INF/lib/, analyze annotations, or even log method call sequences dynamically. 🚀

Would you like to extend this tool with additional capabilities? Let us know in the comments!

This article is inspired by real-world challenges we tackle in our projects. If you're looking for expert solutions or need a team to bring your idea to life,

Let's talk!

    Please fill your details, and we will contact you back

      Please fill your details, and we will contact you back