# ProGuard-Demo
**Repository Path**: hikdah/proguard-demo
## Basic Information
- **Project Name**: ProGuard-Demo
- **Description**: 使用proguard开源工具对Java代码进行混淆的一个代码示例。
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 6
- **Created**: 2025-06-18
- **Last Updated**: 2025-06-18
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 使用开源工具ProGuard实现Java代码混淆
参考文档:
1. [ProGuard官网](https://www.guardsquare.com/proguard)
2. [ProGuardMaven插件文档](https://wvengen.github.io/proguard-maven-plugin/#proguard-mojo.htmloptions)
3. [ProGuard官方配置文档](https://www.guardsquare.com/manual/configuration/usage)
4. [ProGuard配置中文文档](https://www.jianshu.com/p/47ddf0a9d07e)
5. [CSDN-ProGuard使用演示](https://blog.csdn.net/liaomingwu/article/details/123680696)
6. [知乎-ProGuard使用演示](https://zhuanlan.zhihu.com/p/574137579)
## 一、概述
代码混淆是将计算机程序的代码转换成一种功能上等价,但是难以阅读和理解的形式。
## 二、常见的混淆思路
- ### 符号混淆
将函数的符号,如函数名、变量名去除或混淆。
- ### 控制流混淆
混淆程序正常的控制流,使其在功能保持不变的情况下,使其不能清晰地反映原程序的正常逻辑。
- ### 计算混淆
混淆程序的计算流程,或计算流程中使用的数据,使分析者难以分辨某一段代码所执行的具体计算。
- ### 虚拟机混淆
将一组指令集合(如一组x86指令)转化为一组攻击者未知的自定义指令集,并用与程序绑定的解释器解释执行。
## 三、ProGuard工具
**ProGuard**是一个压缩、优化和混淆[Java字节码](https://baike.baidu.com/item/Java字节码/13025120?fromModule=lemma_inlink)文件的免费的工具,它可以删除无用的类、字段、方法和属性。可以删除没用的注释,最大限度地优化字节码文件。它还可以使用[简短](https://baike.baidu.com/item/简短/7933503?fromModule=lemma_inlink)的无意义的名称来重命名已经存在的类、字段、方法和属性。常常用于Android/Java开发用于混淆最终的项目,增加项目被反编译的难度。
处理流程:
- 
1)压缩(shrink):检测并删除未使用的类,字段,方法和属性
2)优化(Optimize):分析并优化方法的字节码
3)混淆(obfuscate):使用简短无意义的名称如a,b等重命名类、方法和属性。
4)预检(preverify):Java平台上对处理后的代码进行预检
## 四、引入项目
ProGuard官方默认提供Gradle插件,不提供Maven插件。但是官方推荐了两个Maven插件[wvengen/proguard](https://github.com/wvengen/proguard-maven-plugin)与[dingxin/proguard](https://github.com/dingxin/proguard-maven-plugin),我们使用第一个插件。
项目使用的框架及语言版本:
| - | 版本 |
| -------- | --------------------------------------- |
| Spring | 2.7.* (2.0+版本都可以,1.5和3.0+未测试) |
| Java | 8 |
| proguard | 2.6.0 |
### 1. 配置xml
```xml
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/jsse.jar
!META-INF/**,!META-INF/versions/**
${project.build.directory}
```
### 2. proguard.cfg文件配置
该文件主要是对项目代码混淆时的参数配置,这里放在项目根目录与pom文件同级
```yaml
# 指定 java 版本
-target 1.8
# 关闭对代码进行优化压缩,开启会删除从未使用的类或者类成员变量等
-dontshrink
# 列出未使用的代码,可打印到标准输出或写入指定文件
#-printusage
# 关闭字节码级别的优化,如果不开启则设置如下配置,默认开启。
-dontoptimize
# 关闭预检,预检主要针对JavaME,Java6以后都不用预检
-dontpreverify
# 不生成大小写混写的类名
-dontusemixedcaseclassnames
# 对类成员的命名混淆采取唯一策略
-useuniqueclassmembernames
# 混淆类名之后,对使用Class.forName('className')之类的地方进行相应替代
-adaptclassstrings
#对异常、注解信息予以保留
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
# 此选项将保存接口中的所有原始名称(不混淆)-->
-keepnames interface ** { *; }
# 此选项将保存所有软件包中的所有原始接口文件(不进行混淆)
#-keep interface * extends * { *; }
#保留参数名,因为控制器,或者Mybatis等接口的参数如果混淆会导致无法接受参数,xml文件找不到参数
-keepparameternames
# 保留枚举成员及方法
-keepclassmembers enum * { *; }
# 不混淆所有类,保存原始定义的注释-
-keepclassmembers class * {
@org.springframework.context.annotation.Bean *;
@org.springframework.beans.factory.annotation.Autowired *;
@org.springframework.beans.factory.annotation.Value *;
@org.springframework.stereotype.Service *;
@org.springframework.stereotype.Component *;
}
#忽略warn消息
-ignorewarnings
#忽略note消息
#-dontnote
#打印配置信息
#-printconfiguration
# 排除混淆 指定的类名且类中的方法也不混淆
-keep class com.example.proguard.ProguardDemoApplication{;}
```
keep可以帮助我们保留我们不需要进行混淆的类、方法或属性,关于上述配置文件中的keep关系整理:
| 保留内容 | 防止删除或重命名 | 防止重命名 |
| :----------------------------- | --------------------- | ------------------------- |
| 类和类成员 | -keep | -keepnames |
| 仅类成员 | -keepclassmembers | -keepclassmembernames |
| 如果类成员存在,保留类和类成员 | -keepclasswithmembers | -keepclasswithmembernames |
更多属性配置,请参照:[ProGuard配置中文文档](https://www.jianshu.com/p/47ddf0a9d07e)
### 3. 项目结构
```basic
├── pom.xml
├── proguard.cfg
└── src
├── main
│ ├── java
│ │ └── com
│ │ └── example
│ │ └── proguard
│ │ ├── ProguardDemoApplication.java
│ │ └── controller
│ │ └── IndexController.java
│ └── resources
│ └── application.yml
└── test
```
### 4. 注意事项
- **不混淆反射代码。(class.forName("类名"))**
- **不混淆需要bean注入的类。(因为我们没有给bean指定id,那么此时的bean的唯一标识的就是name。)**
- **不混淆aop切面的类或方法。(原因与上述大致)**
- **混淆之后可能会有很多奇怪的问题导致项目启动失败,需要根据实际情况进行放行(不混淆)。**
- **对于混淆成功了的项目也需要多进行测试,保证其功能与接口完成与未混淆的源码功能一致。**
## 五、成功演示
### 1. 未混淆代码反编译演示
将项目正常打包后通过反编译工具(JD)进行查看:

### 2. 混淆后代码反编译演示
将项目代码混淆后通过反编译工具查看

### 3. 使用命令启动混淆后的jar包
```java
java -jar proguard-1.0.0-SNAPSHOT.jar
```
请求接口进行测试
