关注我的公众号:【编程朝花夕拾】,可获取首发内容。

01 引言
企业中为了公司的发展,通常会采用分析竞品产品、业务等方式来学习以及弥补自己业务的不足。作为底层的开发人员自认也会去扒竞品公司对应产品的代码,分析亮点以及可取之处,来精进自己的技术以及扩展自己的产品。
通过技术手段通过会使用反编译的方式来解析二进制文件。但是有不少产品使用的代码混淆的技术,大大的提升了逆向工程的难度。
今天,我们就通过**Spring Boot + ProGuard**的实战项目,来给大家好好聊聊Java代码混淆这件事。
02 什么是代码混淆
2.1 简介
代码混淆(Obfuscation)就是把有意义的类名、方法名、变量名改成毫无意义的字母组合,让逆向工程师看得头皮发麻,但又不会影响程序正常运行。
简单来说,就是这样:
java
public class UserService {
public String getUserPassword(String username) { ... }
}
// 混淆后
public class UserService {
public String a(String b) { ... }
}
2.2 工具
**ProGuard**是Java领域最经典的代码混淆工具,主要功能如下:
| 功能 | 说明 |
|---|---|
| 混淆(Obfuscate) | 把类名、方法名、变量名变成a、b、c |
| 优化(Optimize) | 删除无用代码、内联方法、简化逻辑 |
| 压缩(Shrink) | 移除未使用的类和方法,减小JAR体积 |
| 预检(Preverify) | 为Java 6+添加字节码验证信息 |
插件的地址:github.com/wvengen/pro...
03 实战
本是实战将通过sprinboot+proguard-maven-plugin插件实现代码混淆的逻辑。
3.1 项目结构
bash
java-confusion/
├── pom.xml # Maven配置(含ProGuard插件)
├── proguard.conf # 混淆配置文件
└── src/main/java/com/example/demo/
├── DemoApplication.java # 启动类
├── controller/UserController.java
├── entity/User.java
└── service/UserService.java
3.2 Maven依赖
xml
<plugin>
<groupId>com.github.wvengen</groupId>
<artifactId>proguard-maven-plugin</artifactId>
<version>2.7.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<!-- 打包的時候混淆 -->
<goal>proguard</goal>
</goals>
<configuration>
<obfuscate>true</obfuscate>
<!-- 混淆之前的jar -->
<injar>${project.build.finalName}.jar</injar>
<!-- 混淆之后的jar -->
<outjar>${project.build.finalName}-obfuscated.jar</outjar>
<!-- 混淆时的规则文件 -->
<proguardInclude>${basedir}/proguard.conf</proguardInclude>
<libs>
<!-- ProGuard依赖JDK的核心库 -->
<lib>${java.home}/lib/rt.jar</lib>
</libs>
<!-- 自动生成库配置 --> <generateTemporaryConfigurationFile>true</generateTemporaryConfigurationFile>
</configuration>
</execution>
</executions>
</plugin>
执行命令:
bash
mvn clean package
打包完成后,会生成一个xxxx-obfuscated.jar后缀的混淆包。
3.3 核心配置解析
核心的配置文件是proguard.conf。
最基础的优化设置
| 配置 | 作用 |
|---|---|
-optimizationpasses 5 |
优化5次,次数越多效果越好,但编译越慢 |
-dontusemixedcaseclassnames |
混淆时不混用大小写,避免Windows文件系统冲突 |
-dontskipnonpubliclibraryclasses |
不跳过非公共库类,全部处理 |
-ignorewarnings |
忽略所有警告,防止打包中断 |
-verbose |
输出详细的混淆过程信息 |
SpringBoot 相关
properties
-keep class org.springframework.** { *; }
⚠️ 重要!Spring大量使用反射和注解,混淆必挂!
不仅是Spring,这些也必须保留:
- 所有被Spring管理的Bean(Controller、Service、Repository)
- 注解类
- 配置文件类
应用层保留规则
项目里这几个类是核心,必须保留:
properties
# 保留 DemoApplication 类的所有成员不被混淆
# 因为包含 @SpringBootApplication 注解和 main 方法入口
-keep class com.example.demo.DemoApplication { *; }
# 保留 User 实体类的公开字段和方法
# 实体类需要被 JSON 序列化/反序列化,字段名必须保留
-keep public class com.example.demo.entity.User {
public <fields>; # 保留所有公开字段
public <methods>; # 保留所有公开方法
}
# Controller保留方法(路由映射需要)
-keep public class com.example.demo.controller.UserController {
public <methods>;
}
# 此选项将保存接口中的所有原始名称(不混淆)
# Spring 依赖注入需要通过方法名反射调用
-keepnames interface ** { *; }
04 测试效果
我们直接打包看看日志:

打包完成之后会生成一些文件:

-
demo-obfuscation-1.0.0.jar::混淆之前的jar
-
demo-obfuscation-1.0.0-obfuscated.jar:混淆之后的jar
-
generated-proguard.conf:依赖的库
-
proguard_map.txt:是混淆的基本映射
-
proguard_seed:混淆的原始列表
05 小结
代码混淆不是银弹,只能加大逆向工程的难度。使用时,应该注意:
- ProGuard是Java混淆的事实标准,配置灵活且功能强大
- Spring Boot项目混淆要格外小心,反射和注解是重灾区
- 混淆后必须全面测试,否则上线就是事故
- 混淆不是银弹,核心逻辑还是得上服务端
觉得有用的话,点个在看转发支持一下,关注我,持续更新更多硬核干货!