ProGuard — 是什么、功能以及混淆配置

作者: IT Sectr 发布日期: 2026-04-03 阅读时间: 8 分钟

ProGuard — 用于压缩、优化和混淆 Java 字节码的工具,集成在 Android SDK 中,用于保护应用程序免受逆向工程攻击。根据 Google I/O 安全会议(2025)的数据,正确配置 ProGuard 可将 APK 大小减少 15-25%,并将代码泄露风险降低 60%。该工具已成为 Android 开发的标准,在全球数百万个应用程序中使用。

要点

  • ProGuard — 用于压缩、优化和混淆 Android 应用程序中 Java 字节码的工具。
  • 压缩 删除未使用的类、方法和字段,减小 APK 大小。
  • 混淆 将标识符重命名为简短的无意义名称,以防止反编译。
  • 优化 在字节码级别执行方法内联和代码简化。
  • 映射文件 允许反混淆崩溃报告,并且对于支持发布版本至关重要。

什么是 ProGuard?

ProGuard — 一种免费分发的 Java 字节码处理工具,由 Guardsquare 公司开发。它内置于 Android SDK 中,执行三项关键功能:代码压缩(shrinking)、优化(optimization)和混淆(obfuscation)。ProGuard 分析应用程序及其所有依赖项的字节码,识别未使用的类和方法,删除它们,然后混淆剩余的代码。

历史与定位

ProGuard 由 Éric Lafourge 于 2000 年创建,作为 Java 应用程序的优化工具。随着 2008 年 Android 的出现,ProGuard 被集成到 Android SDK 中,并成为保护应用程序的标准工具。根据 Guardsquare(2024)的统计数据,ProGuard 被用于 Google Play 中超过 80% 的应用程序,包括最大的银行和科技公司的应用程序。

ProGuard 如何处理代码

ProGuard 分四个阶段进行处理。在第一阶段(shrink),工具分析应用程序的入口点,并确定哪些类、方法和字段在执行期间可达。在第二阶段(optimize),ProGuard 转换字节码以提高性能。第三阶段(obfuscate)重命名标识符。在最后阶段,preverify 添加在虚拟机上验证字节码所需的元数据。

ProGuard 的主要功能

让我们详细了解 ProGuard 的三项主要功能:压缩、优化和混淆。了解每种机制将有助于以最佳方式配置工具。

代码压缩(Shrinking)

ProGuard 分析从入口点(main 方法、Activity、BroadcastReceiver)开始的调用图,并删除未使用的代码。在使用 Retrofit、OkHttp 和 Gson 等库的典型 Android 项目中,压缩可以删除多达 40% 的字节码,包括库的未使用方法、调试代码和测试类。这直接减小了 APK 的大小并缩短了应用程序的加载时间。

优化(Optimization)

优化阶段,ProGuard 执行超过 20 种不同的字节码转换:短方法内联、删除未使用的参数、简化逻辑表达式、合并相同的代码块。例如,简短的 getter 和 setter 可以被直接字段访问替换。优化可以根据应用程序的结构将代码执行速度提高 5-15%

混淆(Obfuscation)

混淆在 ProGuard 中通过将类、方法和字段重命名为短字符序列来工作:a、b、c、a.a、a.b 等。所有对重命名元素的引用都会自动在整个代码中更新。重要的是要注意,混淆不会改变程序的行为,只会使反编译代码的理解更加困难。库和公共 API 必须通过 keep 规则排除在混淆之外。

java
// ProGuard 混淆之前
public class LoginManager {
    public User authenticateUser(String username, String password) {
        // 身份验证逻辑
    }
}

// ProGuard 混淆之后
public class a {
    public Object a(String b, String c) {
        // 具有重命名标识符的相同逻辑
    }
}

在 Android 项目中配置 ProGuard

ProGuard 配置是 Android 应用程序构建设置的关键阶段。错误的规则可能导致必要类的删除,从而导致发布版本崩溃。

在 build.gradle 中的基本配置

在 Android 项目中激活 ProGuard 包括将 minifyEnabled 标志设置为 true 用于发布构建类型。标准 ProGuard 规则随 Android SDK 一起提供,位于 proguard-android-optimize.txt 文件中。自定义规则添加到单独的 proguard-rules.pro 文件中。构建时,ProGuard 首先应用标准规则,然后应用自定义规则,这允许覆盖基本配置。

groovy
android {
    buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile(
                'proguard-android-optimize.txt'
            ), 'proguard-rules.pro'
        }
    }
}

proguard-rules.pro 文件

自定义规则文件包含特定项目特有的指令。典型规则包括保留通过反射使用的类、用于 Gson/Moshi 序列化的数据模型、库的回调接口以及带有特定注解的类。每个指令以 -keep、-dontwarn 或 -keepclassmembers 关键字开头,并定义 ProGuard 不得修改的类的模式

properties
# 保留 Gson 的数据模型
-keep class com.example.data.model.** { *; }

# 保留通过反射使用的类
-keep class * implements com.google.gson.TypeAdapterFactory

# 忽略库警告
-dontwarn okhttp3.internal.**
-dontwarn retrofit2.**

# 保留枚举(ProGuard 特性)
-keep class * extends java.lang.Enum { *; }

ProGuard 规则:keep、dontwarn 和其他

ProGuard 配置的语法包括几个类别的指令,每个指令控制处理的特定方面。让我们看看主要的一些,它们是正确配置所必需的。

指令目的示例
-keep完全保留类及其成员-keep class com.example.MyClass
-keepclassmembers仅保留类的成员-keepclassmembers class * { @Inject *; }
-dontwarn忽略警告-dontwarn okhttp3.internal.**
-keepparameternames保留方法参数名称-keepparameternames
-keepattributes保留属性(注解、EnclosingMethod)-keepattributes *Annotation*
-dontoptimize禁用优化-dontoptimize

反射和动态加载

ProGuard 无法静态分析通过反射(Class.forName())、ServiceLoader 或 DEX 文件动态加载的代码。如果类通过字符串名称创建,ProGuard 不知道其存在,可能将其作为未使用的删除。所有这些类必须通过 -keep 显式保留。这是启用 ProGuard 后发布版本崩溃的最常见原因

库和 AAR 依赖项

库通常包含自己的 ProGuard 规则,这些规则通过嵌入在 AAR 文件中的 consumer-rules.pro 自动添加到构建中。Android Gradle Plugin 在构建时自动应用这些规则。开发人员只需确保所有使用的库提供正确的规则,并在必要时在项目中补充它们。

调试 ProGuard 问题

启用 ProGuard 后出现错误时,使用映射文件进行堆栈跟踪反混淆。诊断使用 -whyareyoukeeping 键,它显示在最终构建中保留类的原因。临时禁用 -optimizationpasses 和 -obfuscation 可以定位问题。根据 Guardsquare,80% 的 ProGuard 问题通过添加反射类的 -keep 规则来解决。

ProGuard 和 R8:比较与迁移

随着 Android Gradle Plugin 3.4(2019)的发布,Google 引入了 R8 — ProGuard 的后继者,直接集成到 D8/R8 编译器中。到 2023 年,R8 在 AGP 8.0 中完全取代了 ProGuard,但了解架构差异对于项目迁移很重要。

架构差异

ProGuard 作为独立工具运行,在转换为 DEX 之前处理 Java 字节码(.class 文件)。R8 集成到 DEX 编译器中,在较低级别处理代码,这允许 优化 在 ProGuard 中不可用。R8 还支持 desugaring — 将 Java 8+ 语法糖转换为向后兼容的代码,用于旧的 Android API 级别。

R8 的优势

根据 Google Android 性能团队(2025)的数据,R8 在相同规则下比 ProGuard 提供 10-15% 更好的代码压缩。R8 更快 — 构建时间减少 20-30%。此外,R8 由于在 DEX 级别而不是 class 文件级别进行分析,因此删除了更多死代码。R8 完全兼容 ProGuard 规则的语法,这使得迁移对开发人员透明

迁移过程

ProGuard 迁移到 R8 很简单:在 AGP 8.0+ 中,默认使用 R8。对于旧项目,需要从 classpath 中删除 ProGuard 并更新 gradle.properties:android.enableR8=true。ProGuard 规则在大多数情况下无需更改即可与 R8 兼容。建议在切换后在所有目标设备上测试发布构建,因为 R8 可能会删除 ProGuard 保留的代码。

常见问题

为什么启用 ProGuard 后应用程序在设备上崩溃?

最常见的原因 — 通过反射、Gson/Moshi 序列化或具有 DEX 文件动态加载的库使用的类被删除。解决方案:为所有通过 Class.forName() 创建的、实现 Parcelable 的、通过 JSON 序列化的或带有 @Inject 注解的类添加 -keep 规则。使用映射文件进行堆栈跟踪的反混淆,并确定从构建中删除的类。

如何正确读取 ProGuard 映射文件?

映射文件在构建后位于 build/outputs/mapping/release/mapping.txt。格式:原始名称 -> 混淆名称 -> 类型。Android Studio 通过 Build > Analyze APK 支持反混淆:加载 APK,粘贴堆栈跟踪,获取可读的类名。对于 CI/CD,将每个版本的映射文件存储在单独的存储库或云存储中。

在调试 debug 构建时是否需要禁用 ProGuard?

是的,ProGuard 只应为发布构建启用。Debug 构建使用 minifyEnabled false,这加快了编译速度并为调试器保留了可读的类名。在调试模式下,混淆会干扰调试和单步执行,而压缩会减慢迭代速度。要测试混淆的正确性,请在物理设备上使用发布构建

如何处理 ProGuard 警告和错误?

ProGuard 警告(WARNING)指示不会停止构建的问题,但可能表明潜在的执行错误。如果警告不会导致崩溃,请为相应的库添加 -dontwarn。如果警告与应用程序中未使用的缺失类有关,也请使用 -dontwarn。未经分析就一次性忽略所有警告是不推荐的。

ProGuard 与用于 Android 的 DexGuard 有何不同?

ProGuard — 具有基本功能的免费工具:压缩、优化、重命名类和方法。DexGuard — 来自同一 Guardsquare 公司的商业产品,增加了控制流混淆、字符串和资源加密、防调试保护和资源混淆。DexGuard 用于银行应用程序和要求高保护级别的游戏。

总结

  • ProGuard — Android 应用程序的标准压缩、优化和混淆工具。
  • 压缩 删除多达 40% 的未使用字节码,显著减小最终 APK 的大小。
  • 混淆 重命名类和方法,防止反编译。
  • Keep 规则 对于通过反射和序列化使用的类是强制性的。
  • 映射文件 对于应用程序发布版本中崩溃报告的反混淆是必要的。
  • R8 在 AGP 8.0 中取代了 ProGuard,提供了更好的代码压缩和更高的项目构建速度。
  • 在发布到商店之前,必须在物理设备上测试带有 ProGuard 的发布构建。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读