Using ProGuard, Xjar, and ClassFinal for Java JAR Obfuscation and Encryption in Spring Boot Projects
This article explains how to protect Java backend code deployed on user servers by applying ProGuard, Xjar, and ClassFinal for JAR obfuscation and encryption, detailing Maven configurations, startup commands, decompilation results, and best‑practice integration of both tools in a Spring Boot project.
Background
The core code module of the project is deployed on user servers; directly copying JAR files can lead to data and code leakage. To prevent technically capable users from decompiling the program, ProGuard and Xjar are used for obfuscation and encryption.
Note: Encryption only raises the difficulty of obtaining the code; there is no absolutely secure method, and higher security levels increase development, operation, and deployment costs, so the appropriate level of encryption is the best choice.
Introduction
1. ProGuard is a free tool that compresses, optimizes, and obfuscates Java bytecode, removing unused classes, fields, methods, and attributes, and renaming existing ones with short meaningless names. It is often used in Android development to increase the difficulty of reverse engineering.
2. Xjar
Spring Boot JAR security encryption runtime tool, also supports native JAR.
Encrypts resources inside the JAR and uses an extended ClassLoader to provide a dynamic decryption runtime, preventing source code leakage and decompilation.
Features
No code intrusion; just encrypt the compiled JAR with the tool.
Full in‑memory decryption, reducing the risk of source or bytecode leakage.
Supports all JDK built‑in encryption algorithms.
Allows selection of which bytecode or resource files to encrypt.
Supports Maven plugin for convenient encryption.
Generates a Go launcher dynamically to protect passwords.
3. ClassFinal is a Java class file security encryption tool that can encrypt JAR or WAR packages without modifying any project code and is compatible with Spring Framework, preventing source code leakage or bytecode decompilation.
Features
No need to modify original project code; just encrypt the compiled JAR/WAR.
Running the encrypted project does not require modifying Tomcat, Spring, etc.
Supports ordinary JAR, Spring Boot JAR, and standard Java web WAR packages.
Compatible with frameworks that scan annotations or generate bytecode at startup (e.g., Spring, Swagger).
Supports Maven plugin for automatic encryption during packaging.
Supports encryption of dependencies under WEB‑INF/lib or BOOT‑INF/lib.
Pre‑research of ClassFinal
ClassFinal can also achieve code encryption. After encryption, decompiled methods return null or 0 , and the method bodies are removed. The encrypted JAR must be started with javaagent . Compared with Xjar, decompilation directly shows an Internal Error .
1. Module pom file inclusion
<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. Startup methods
1) No‑password startup
java -jar gnss-server-1.0.0-encrypted.jar2) Password startup
java -javaagent:gnss-server-1.0.0-encrypted.jar="-pwd 123456" -jar gnss-server-1.0.0-encrypted.jar3) Decompilation result: all methods return 0 or null , and the method bodies are empty.
Introducing ProGuard
1. Add proguard.cfg to the module
# Specify Java version
-target 1.8
# Do not shrink (remove unused code)
-dontshrink
# Disable bytecode‑level optimization
-dontoptimize
# Do not generate mixed‑case class names
-dontusemixedcaseclassnames
# Use unique class member names
-useuniqueclassmembernames
# Adapt class strings after obfuscation
-adaptclassstrings
# Keep attributes (exceptions, annotations, etc.)
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
# Keep original interface names
-keepnames interface ** { *; }
# Keep parameter names for controllers, MyBatis, etc.
-keepparameternames
# Keep enum members and methods
-keepclassmembers enum * { *; }
# Keep getters and setters
-keepclassmembers public class * { void set*(***); *** get*(); }
# Keep Spring‑related annotations
-keep @org.springframework.context.annotation.Bean class * { *; }
-keep @org.springframework.context.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 and notes
-ignorewarnings
-dontnote
# Print configuration
-printconfiguration
# Do not obfuscate the main class
-keep class com.nick.GnssApplication { public static void main(java.lang.String[]); }2. Add ProGuard plugin to module pom
com.github.wvengen
proguard-maven-plugin
2.6.0
package
proguard
${project.build.finalName}.jar
${project.build.finalName}.jar
true
${project.basedir}/proguard.cfg
${java.home}/lib/rt.jar
${java.home}/lib/jce.jar
${java.home}/lib/jsse.jar
!META-INF/**,!META-INF/versions/9/**.class
${project.basedir}/targetIntroducing Xjar
1. Parent pom inclusion
<?xml version="1.0" encoding="UTF-8"?>
<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">
...
<build>
<plugins>
...
<!-- Code encryption Xjar -->
<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>
</plugins>
</build>
</project>2. Module pom inclusion (must be the last plugin)
<plugin>
<groupId>com.github.core-lib</groupId>
<artifactId>xjar-maven-plugin</artifactId>
<version>v2.0.7</version>
</plugin>Combining ProGuard and Xjar
Integrate the ProGuard and Xjar plugins in the correct order (ProGuard first, Xjar last) to ensure both obfuscation and encryption succeed.
1. Full parent pom
<?xml version="1.0" encoding="UTF-8"?>
<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">
...
<build>
<plugins>
...
<!-- ProGuard plugin (as shown earlier) -->
...
<!-- Spring Boot repackage plugin -->
...
<!-- Xjar plugin (as shown earlier) -->
</plugins>
</build>
</project>2. Full proguard.cfg (same as above)
3. Full module pom (inherits parent and adds Xjar as last plugin)
<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">
<parent>
<artifactId>nick-server</artifactId>
<groupId>com.nick</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.nick</groupId>
<artifactId>gnss-server</artifactId>
<version>1.0.0</version>
...
<build>
<plugins>
...
<!-- Xjar plugin must be the last one -->
<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>
</plugins>
</build>
</project>After building the project with mvn package , the resulting JAR is both obfuscated by ProGuard and encrypted by Xjar. Decompilation shows methods returning 0 or null , confirming successful protection.
Conclusion: Combining ProGuard (for bytecode obfuscation) and Xjar (for runtime encryption) provides a robust solution to protect Java backend code from reverse engineering while keeping the deployment process simple.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.