这是有问题的配置设置:-keep @interface *
此帖子引用了此设置:https://stackoverflow.com/a/17437740/367544
在Proguard手册中:https://www.guardsquare.com/en/proguard/manual/troubleshooting#notkept
但是手册(或帖子)并没有解释此配置设置的工作原理或原因。我认为此配置值将保留应用程序中已定义的任何注释。我在这里强调了定义这个词,因为我想将它与使用的注释进行比较。因此,如果我在我的代码中定义了注释,例如public @interface MyAnnotation {}
,那么我希望这个配置设置能够保留它。但是,如果我在另一个类public class MyClass { @MyAnnotation public void run(){} }
中使用我的注释,那么我不期望此配置设置将其保留在那里。我认为要保留使用它的注释,您需要一个像-keep class * { @interface <methods>; }
这样的设置。但是,我的理解显然是错误的,因为-keep @interface *
配置设置确实保留了他们使用的注释。
有人可以解释为什么-keep @interface *
配置设置会影响其他类中使用的注释吗?此外,Proguard手册从未解释过如何使用@interface
关键字。这是任何注释的通配符吗?或者它是否像我的示例public @interface MyAnnotation {}
中那样引用了注释的定义?或者它完全是另一回事?
答案 0 :(得分:1)
当编译每个接口时,即使使用proguard,它也应该创建一个可以在java虚拟机中使用的有效类文件。 Java具有特定的命名规则,用于将包中的接口和类与文件连接起来。
因此,例如,即使包VeryImportantInterface
的接口com.mycompany.mypackage
被混淆,结果你得到:
包a
中的接口b.c.d
java期望在名为a
b.c.d
中的接口a.class
类似的规则适用于内部类和接口。
因此,如果您对类或接口的定义进行模糊处理,则必须在其中随处提及其模糊名称。否则,如果将类MyClass.class
混淆为a.class
和另一个类,例如MyClassReference
仍然将此类引用为MyClass
,然后ClassNotFoundException
首次尝试使用MyClassReference
时会引发MyClass
。
关于 -keep @interface * 正如ProGuard RefCard
中所述'keep'可防止删除或重命名类和类成员。
ProGuard RefCard还提到可以使用通配符*
*
可用于任意数量的字符(但不包括包分隔符)- 类名
*
指的是任何类,无论其包装如何。- 醇>
*
匹配任何字段或方法
因此,-keep @interface *
根据上述定义适用于public @interface MyAnnotation {}
,因为其名称与通配符*
匹配。由于根据定义MyAnnotation
不会被删除,因此不会从任何地方删除它。
相反,-keep class * { @interface <methods>; }
更具体,只保留注释的用法。
要考虑的另一件事是keep之后是Class specification。并基于Class specification
@ specifications可用于将类和类成员限制为使用指定的注释类型注释的类。注释类型就像类名一样指定。
在缩小过程中,专业保护将删除所有直接或间接使用的方法和成员加上-keep
指定的方法和成员。但是它没有明确提到它对注释的作用。
Pro-Guard提到缩小以下内容:
默认情况下,应用收缩;所有类和类成员都被删除,除了各种-keep选项列出的那些,以及它们所依赖的那些,直接或间接。 Shrinking Options 因此,有一种情况可能是专业人员以某种方式检测到注释被使用并防止它在收缩期间被移除。 另一种情况是注释被认为是方法的元数据,而不是被认为是成员。 在proguard文档中,它实际上并不明显或有很好的文档记录。
您可以使用-whyareyoukeeping @interface *
和-verbose
从Prog-Guard获取有关保留相关接口的原因的反馈。
更新:
由于上述配置指令的结果是:
... is kept by a directive in the configuration.
,实际上只能得出结论-keep @interface *
。因此,它没有提供任何额外的澄清。如果没有关于Pro-Guard文档的任何具体说明,我认为可能有以下两种可能的解释:
1. proguard收缩步骤认为注释用在代码的某些部分,因此需要而不是减少。
2. class_specification @interface *
匹配带注释的方法和注释声明。