Java Code Obfuscation and Encryption with ProGuard, Xjar, and ClassFinal
The guide explains how to protect a Java core module deployed on user servers by integrating ProGuard for bytecode obfuscation, Xjar for JAR encryption, and ClassFinal for class‑file encryption, providing Maven plugin configurations, startup commands, and verification that the combined approach renders decompiled code empty or unreadable.
Background : The core module of a project is deployed on user servers. Directly delivering JAR files can lead to data and code leakage. To prevent reverse‑engineering, ProGuard and Xjar are used for obfuscation and encryption.
Introduction :
ProGuard – a free tool that compresses, optimizes, and obfuscates Java bytecode, removing unused classes, fields, methods, and renaming remaining ones with meaningless identifiers. Commonly used in Android projects.
Xjar – a Spring Boot JAR security encryption tool that encrypts resources inside the JAR and uses a custom ClassLoader for dynamic decryption at runtime, preventing source code leakage.
ClassFinal – a Java class file encryption tool that encrypts JAR/WAR without modifying source code, compatible with Spring Framework.
ClassFinal research :
Encrypted JARs return null or 0 for all methods after decompilation. Startup requires java -javaagent mode.
1. Module pom inclusion
<plugin>
<groupId>net.roseboy</groupId>
<artifactId>classfinal-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<password>#</password> <!-- password not needed for obfuscation -->
<packages>com.nick.gnss</packages> <!-- comma‑separated packages -->
<excludes>org.spring</excludes>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>classFinal</goal>
</goals>
</execution>
</executions>
</plugin>2. Startup methods
No‑password:
java -jar gnss-server-1.0.0-encrypted.jarWith password:
java -javaagent:gnss-server-1.0.0-encrypted.jar="-pwd 123456" -jar gnss-server-1.0.0-encrypted.jarDecompiled result: all methods return 0 or null , bodies are empty.
ProGuard integration :
1. Add proguard.cfg to module
# Java version
-target 1.8
# Disable shrinking and optimization
-dontshrink
-dontoptimize
# Keep class name case consistent
-dontusemixedcaseclassnames
-useuniqueclassmembernames
-adaptclassstrings
# Preserve annotations and signatures
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
-keepnames interface ** { *; }
-keepparameternames
-keepclassmembers enum * { *; }
-keepclassmembers public class * { void set*(***); *** get*(); }
-keep @org.springframework.context.annotation.Bean class * { *; }
-keep @org.springframework.context.beans.factory.annotation.Autowired class * { *; }
-keep @org.springframework.context.annotation.Configuration class * { *; }
-ignorewarnings
-dontnote
-printconfiguration
-keep class com.nick.GnssApplication { public static void main(java.lang.String[]); }2. Maven plugin configuration
<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>Make sure the ProGuard plugin runs before the Spring Boot repackage plugin.
Xjar integration :
1. Parent pom addition
<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>Place this plugin as the last one in the module pom to ensure Xjar runs after ProGuard.
Combined ProGuard + Xjar :
Use the full parent pom and proguard.cfg shown above, then add the Xjar plugin at the end. Build with mvn package . The resulting JAR is both obfuscated and encrypted, and runs successfully.
Testing shows the protected JAR cannot be decompiled meaningfully, confirming the effectiveness of the combined approach.
Java Tech Enthusiast
Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!
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.