ProGuard 默认混淆对象变量名为单字母,但需禁用-dontobfuscate并避免过度-keepclassmembers;被序列化注解、反射调用或Serializable影响的字段易逃过混淆,应通过mapping.txt和反编译验证,精准保留必要字段。

要让对象变量名在反编译后仍不可读,ProGuard 默认就会做这件事——它把所有非保留的字段(包括对象类型的变量)重命名为 a、b、c 这类单字母名。但前提是:你不能错误地保留了它们,也不能关闭混淆本身。
确保变量名被混淆的关键配置
ProGuard 默认开启混淆(-obfuscate),但很多项目因兼容性问题误加了 -dontobfuscate 或过度使用 -keepclassmembers,导致变量名原样暴露。检查你的规则文件(如 proguard-rules.pro 或 proguard.cfg)中是否包含以下危险项:
- -dontobfuscate → 必须删除,否则整个混淆环节失效
- -keepclassmembers class * { <fields> } → 会保留所有字段名,包括对象变量,慎用
- -keepnames class com.example.MyClass → 只保留类名,但字段仍可能被混淆;若想连字段也保留,会额外加 -keepclassmembernames,这同样要避免
哪些对象变量名会被保留?常见陷阱
不是所有对象变量都会被混淆。以下情况会让变量名“逃过”混淆:
- 被 @SerializedName、@JsonProperty 等序列化注解标记的字段(如 Gson/Fastjson 使用的 POJO 字段)——需配合 -keepattributes Signature,Annotation 和针对性 -keepclassmembers,但仅保留注解本身,不等于保留变量名;若写成 -keepclassmembers class * { <fields> } 就全放行了
- 被反射直接调用的字段(如
obj.getClass().getDeclaredField("userName"))——必须用 -keepclassmembers 保留该字段名,否则运行时报NoSuchFieldException - 实现了 Serializable 接口且未自定义 serialVersionUID 的类,其字段名可能影响序列化兼容性,部分团队会保守保留
验证对象变量是否真被混淆
混淆完成后,不要只看日志。直接反编译输出的 APK 或 JAR 文件(用 JADX-GUI 或 JD-GUI)打开某个实体类,观察字段声明:
立即学习“Java免费学习笔记(深入)”;
- 混淆前:
private User currentUser; - 混淆后应类似:
private User a;或private User b;(不是private User currentUser;) - 如果看到字段名仍是
currentUser,说明它被某条 -keep 规则意外保护了,需顺藤摸瓜查 mapping.txt 中该字段是否出现在 seeds 列表里
精准控制:只保留必要字段,其余一律混淆
如果你确实有少数对象变量必须保持原名(比如 JSON 映射字段),推荐显式、最小化保留:
- 保留特定类的特定字段:
-keepclassmembers class com.example.User { public java.lang.String userName; } - 保留带注解的字段(仅限注解本身,不保名):
-keepclassmembers class * { @com.google.gson.annotations.SerializedName <fields>; } - 避免通配:
-keepclassmembers class * { <fields> }是“全放开”,等同于没混淆字段


















