Backend Development 22 min read

Using ProGuard, Xjar, and ClassFinal to Obfuscate and Encrypt Java JARs in Spring Boot Projects

This article explains how to protect Java server-side code from decompilation by applying ProGuard shrinking/obfuscation and Xjar/ClassFinal encryption, provides detailed Maven plugin configurations, sample pom.xml snippets, command‑line launch options, and demonstrates the resulting protected JARs with screenshots.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Using ProGuard, Xjar, and ClassFinal to Obfuscate and Encrypt Java JARs in Spring Boot Projects

Background

The core modules of a project are deployed directly to user servers by copying JAR files, which can lead to source and bytecode leakage; therefore ProGuard and Xjar are used to obfuscate and encrypt the JARs.

Encryption raises the barrier for reverse engineering but is not absolute; the appropriate level of protection should balance security and operational cost.

Introduction

ProGuard is a free tool that compresses, optimizes, and obfuscates Java bytecode, removing unused classes, fields, methods, and renaming remaining ones with meaningless short names. It is commonly used in Android projects to increase decompilation difficulty.

Xjar is a Spring Boot JAR security tool that encrypts JAR resources and uses a custom ClassLoader to decrypt them at runtime, preventing source leakage and decompilation.

ClassFinal is another Java class encryption tool that can encrypt JAR/WAR packages without modifying source code, compatible with Spring Framework.

Features of Xjar

No code intrusion – just encrypt the compiled JAR.

Full in‑memory decryption to reduce the risk of bytecode leakage.

Supports all JDK built‑in encryption algorithms.

Selective encryption of bytecode or other resource files.

Provides a Maven plugin for convenient integration.

Generates a Go launcher to hide the password.

Features of ClassFinal

No source code changes required; encrypt the compiled JAR/WAR directly.

Works without modifying Tomcat, Spring, etc.

Supports plain JAR, Spring Boot JAR, and standard WAR packages.

Compatible with frameworks that scan annotations or generate bytecode at startup.

Provides a Maven plugin for automatic encryption during packaging.

Can encrypt dependencies located under WEB-INF/lib or BOOT-INF/lib .

ClassFinal Integration Example

1. Add the ClassFinal plugin to the module pom.xml :

<plugin>
    <groupId>net.roseboy</groupId>
    <artifactId>classfinal-maven-plugin</artifactId>
    <version>1.2.1</version>
    <configuration>
        <password>#</password>
<packages>com.nick.gnss</packages>
<excludes>org.spring</excludes>
    </configuration>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>classFinal</goal>
            </goals>
        </execution>
    </executions>
</plugin>

2. Launch the encrypted JAR:

• Without password:

java -jar gnss-server-1.0.0-encrypted.jar

• With password:

java -javaagent:gnss-server-1.0.0-encrypted.jar="-pwd 123456" -jar gnss-server-1.0.0-encrypted.jar

After decompilation, all methods return 0 or null , and the method bodies are empty.

ProGuard Integration

1. Add a proguard.cfg file to the module with the following options (excerpt):

# Java version
-target 1.8
# Disable shrinking and optimization
-dontshrink
-dontoptimize
# Keep class names case‑insensitive
-dontusemixedcaseclassnames
# Use unique member names
-useuniqueclassmembernames
# Adapt class strings for reflection
-adaptclassstrings

# Preserve annotations and exception information
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
# Keep interface names
-keepnames interface ** { *; }
# Keep parameter names for Spring MVC / MyBatis
-keepparameternames
# Keep enum members
-keepclassmembers enum * { *; }
# Keep getters/setters
-keepclassmembers public class * { void set*(***); *** get*(); }
# Keep Spring annotations
-keep @org.springframework.context.annotation.Bean class * { *; }
-keep @org.springframework.context.beans.factory.annotation.Autowired class * { *; }
-keep @org.springframework.context.annotation.Value class * { *; }
-keep @org.springframework.stereotype.Service class * { *; }
-keep @org.springframework.stereotype.Component class * { *; }
-keep @org.springframework.web.bind.annotation.RestController class * { *; }
-keep @org.springframework.context.annotation.Configuration class * { *; }
# Suppress warnings
-ignorewarnings
-dontnote
-printconfiguration
# Do not obfuscate the main class
-keep class com.nick.GnssApplication { public static void main(java.lang.String[]); }

2. Add the ProGuard Maven plugin (must be placed before the repackage plugin):

<plugin>
    <groupId>com.github.wvengen</groupId>
    <artifactId>proguard-maven-plugin</artifactId>
    <version>2.6.0</version>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>proguard</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <injar>${project.build.finalName}.jar</injar>
        <outjar>${project.build.finalName}.jar</outjar>
        <obfuscate>true</obfuscate>
        <proguardInclude>${project.basedir}/proguard.cfg</proguardInclude>
        <libs>
            <lib>${java.home}/lib/rt.jar</lib>
            <lib>${java.home}/lib/jce.jar</lib>
            <lib>${java.home}/lib/jsse.jar</lib>
        </libs>
        <inLibsFilter>!META-INF/**,!META-INF/versions/9/**.class</inLibsFilter>
        <outputDirectory>${project.basedir}/target</outputDirectory>
    </configuration>
</plugin>

Xjar Integration

1. Add the Xjar Maven plugin to the parent pom.xml (must be the last plugin to execute):

<plugin>
    <groupId>com.github.core-lib</groupId>
    <artifactId>xjar-maven-plugin</artifactId>
    <version>v2.0.7</version>
    <executions>
        <execution>
            <goals>
                <goal>build</goal>
            </goals>
            <phase>package</phase>
            <configuration>
                <password>44889951235894612351265ABD123</password>
                <mode>1</mode>
                <sourceDir>${project.build.directory}</sourceDir>
                <targetJar>${project.build.finalName}_x.jar</targetJar>
                <includes>
                    <include>com/nick/**</include>
                </includes>
            </configuration>
        </execution>
    </executions>
</plugin>

2. The same configuration is added to each module pom.xml after the other plugins.

Full Parent POM Example

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.nick</groupId>
    <artifactId>nick-server</artifactId>
    <version>1.0.0</version>
    <properties>
        <java.version>1.8</java.version>
        <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
    </properties>
    <modules>
        <module>gnss-server</module>
    </modules>
    <dependencyManagement>…</dependencyManagement>
    <build>
        <plugins>
            …
            <!-- ProGuard plugin (must run before repackage) -->
            <plugin>…proguard‑maven‑plugin configuration…</plugin>
            <!-- Spring Boot repackage plugin -->
            <plugin>…spring‑boot‑maven‑plugin configuration…</plugin>
            <!-- Xjar plugin (last) -->
            <plugin>…xjar‑maven‑plugin configuration…</plugin>
        </plugins>
    </build>
</project>

Verification

After building the project with mvn package , the resulting JAR is both obfuscated by ProGuard and encrypted by Xjar (or ClassFinal). Decompiling the JAR shows methods returning 0 or null and empty bodies, confirming the protection works.

The article concludes that combining ProGuard and Xjar provides a practical solution for protecting Java backend code while keeping deployment straightforward.

JavaobfuscationMavenSpring BootEncryptionProGuardXjar
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.