启用Proguard/R8后如何保留构造函数参数名称?
解决方案
核心ProGuard配置规则
结合Kotlin的元数据特性、构造函数参数名保留需求,在proguard-rules.pro中添加以下规则:
保留目标类及其子类的完整结构
确保ProGuard不会移除类的元数据、构造函数标记及成员信息:-keep class my.class.package.name.Destination { *; } -keep public class * extends my.class.package.name.Destination { <init>(...); *; }强制保留参数名称与Kotlin元数据
Kotlin的primary构造函数标记、参数名依赖专属元数据,必须明确保留:-keepattributes RuntimeVisibleParameterAnnotations, MethodParameters, KotlinMetadata -keepparameternames class * extends my.class.package.name.Destination { <init>(...); }KotlinMetadata:保留Kotlin类的元数据,确保primary构造函数标记不丢失;RuntimeVisibleParameterAnnotations/MethodParameters:让参数名称在运行时可被反射读取;keepparameternames:精准锁定目标子类的构造函数参数名保留规则。
针对性关闭混淆
若全局关闭混淆过于宽泛,可仅对目标类禁用参数名混淆:-dontobfuscate class * extends my.class.package.name.Destination
Gradle编译参数补充
在模块的build.gradle(或build.gradle.kts)中添加Kotlin编译参数,确保编译器生成可被ProGuard识别的参数名信息:
Groovy DSL
android { kotlinOptions { jvmTarget = "1.8" freeCompilerArgs += "-Xemit-jvm-type-annotations" freeCompilerArgs += "-java-parameters" } }
Kotlin DSL
android { kotlinOptions { jvmTarget = "1.8" freeCompilerArgs += "-Xemit-jvm-type-annotations" freeCompilerArgs += "-java-parameters" } }
-java-parameters会让Kotlin编译器生成符合Java 8规范的参数名信息,提升ProGuard保留参数名的成功率。
验证方式
构建混淆包后,可通过两种方式验证效果:
- 用
javap -v命令查看目标类字节码,检查LocalVariableTable中是否存在原始参数名; - 在代码中通过反射获取构造函数的
Parameter数组,打印getName()确认名称是否正确,同时检查Kotlin反射的isPrimary属性是否为true。
内容的提问来源于stack exchange,提问作者lotdrops
相关产品推荐
相关产品推荐

