How to Secure Your Spring Boot JAR Against Decompilation with ClassFinal
This guide explains how to protect a Spring Boot release package from source leakage by comparing code obfuscation and encryption, detailing the configuration of the classfinal‑maven‑plugin, launch commands with and without passwords, and binding the encrypted jar to a specific machine.
Scenario
The project must be deployed to a third‑party server while preventing source code exposure; the production startup package needs security processing so that customers cannot retrieve the original code using decompilation tools.
Solution Overview
Two approaches are evaluated:
Code obfuscation using proguard-maven-plugin. It works for single‑module projects but becomes complex in multi‑module setups because of intricate configuration, documentation difficulty, and high risk of errors when deciding which modules to obfuscate.
Code encryption using classfinal-maven-plugin. This method is simpler: a single plugin configuration protects source code, can encrypt .yml, .properties files and Maven dependencies in lib, and supports machine‑binding so the encrypted jar runs only on designated machines.
Implementation with ClassFinal
Add the following plugin configuration to the pom.xml of the Spring Boot application, placing it after the spring-boot-maven-plugin block.
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<!-- ClassFinal plugin for code encryption -->
<groupId>net.roseboy</groupId>
<artifactId>classfinal-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<password>#</password> <!-- # means no password is required at startup -->
<excludes>org.spring</excludes>
<packages>${groupId}</packages> <!-- packages to encrypt, comma‑separated -->
<cfgfiles>application.yml,application-dev.yml</cfgfiles> <!-- config files to encrypt -->
<libjars>hutool-all.jar</libjars> <!-- JARs in lib/ to encrypt -->
<code>xxxx</code> <!-- machine code for binding (replace with generated code) -->
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>classFinal</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>Launch Methods
Without a password:
java -javaagent:xxx-encrypted.jar -jar xxx-encrypted.jarWith a password (replace 密码 with the actual password):
java -javaagent:xxx-encrypted.jar='-pwd=密码' -jar xxx-encrypted.jarMachine‑Binding
Download classfinal-fatjar-1.2.1.jar and run the following command to generate a machine code: java -jar classfinal-fatjar-1.2.1.jar -C Insert the generated code into the <code> element of the plugin configuration. After rebuilding, the encrypted JAR can only start on the machine that produced that code.
Decompilation Result
After encryption, method bodies are cleared while parameters, annotations, and method signatures remain, preserving Swagger documentation scanning. Decompilation shows only method signatures; the actual implementation is absent. Configuration files become blank, and the decryption process occurs entirely in memory without leaving decrypted class files on disk.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Architect
Professional architect sharing high‑quality architecture insights. Topics include high‑availability, high‑performance, high‑stability architectures, big data, machine learning, Java, system and distributed architecture, AI, and practical large‑scale architecture case studies. Open to ideas‑driven architects who enjoy sharing and learning.
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.
