Information Security 20 min read

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.

Java Tech Enthusiast
Java Tech Enthusiast
Java Tech Enthusiast
Java Code Obfuscation and Encryption with ProGuard, Xjar, and ClassFinal

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.jar

With password:

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

Decompiled 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.

JavamavenClassFinalcode obfuscationProGuardXjar
Java Tech Enthusiast
Written by

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!

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.