我最近第一次启用了Proguard的混淆功能,它似乎找到了我的-keep规则中的所有漏洞。
我的keep规则是用注释定义的:带注释的元素将被单独保留。接下来的配置看起来像这样:
# Keep the annotation.
-keep @interface org.mozilla.gecko.mozglue.JNITarget
# Keep classes tagged with the annotation.
-keep @org.mozilla.gecko.mozglue.JNITarget class *
# Keep all members of an annotated class.
-keepclassmembers @org.mozilla.gecko.mozglue.JNITarget class * {
*;
}
# Keep annotated members of any class.
-keepclassmembers class * {
@org.mozilla.gecko.mozglue.JNITarget *;
}
# Keep classes which contain at least one annotated element. Split over two directives
# because, according to the developer of ProGuard, "the option -keepclasseswithmembers
# doesn't combine well with the '*' wildcard" (And, indeed, using it causes things to
# be deleted that we want to keep.)
-keepclasseswithmembers class * {
@org.mozilla.gecko.mozglue.JNITarget <methods>;
}
-keepclasseswithmembers class * {
@org.mozilla.gecko.mozglue.JNITarget <fields>;
}
所有从Reflection/JNI/etc到Java的入口点。使用此注释(或同等配置的、但名称更好的注释)进行注释。
不幸的是,这并不能阻止Proguard重命名作为方法返回类型的类,从而改变其签名并破坏入口点。
例如,Javap揭示了签名为: 的方法 public org.mozilla.gecko.Tab loadUrl(java.lang.String);
从Proguard中显示出来如下:
public mt loadUrl(java.lang.String);
尽管有注释
那么,保留依赖类的神秘keep语法是什么呢?奇怪的是,我告诉它我希望保留一个入口点,它还是继续破坏它…这是预期的行为。在较早的版本中,ProGuard会自动保留所有返回类型和参数类型,但这对许多开发人员来说是不必要的,也是令人困惑的。
例如,对于class# getMethod的反射,返回类型是不相关的。
ProGuard现在打印笔记,如果这样的类型没有被保留。然后,您仍然可以为它添加-keep行。
请参阅ProGuard手册>故障处理>注意:该配置保留入口点'…,而不是描述符类"…"
更新:
ProGuard 5.0 beta3及更高版本的支持
-keep,includedescriptorclasses .......
还自动将类保留在指定的字段类型、返回类型和参数类型中。