谁能解释Proguard配置设置:-保持@interface*



这是有问题的配置设置:-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 {}那样引用注释的定义? 还是完全是别的什么?

编译每个接口时,即使使用 proguard,它也应该创建一个可以在 java 虚拟机中使用的有效类文件。 Java 具有特定的命名规则,用于将包中的接口和类与文件连接起来。

因此,例如,即使包com.mycompany.mypackage的接口VeryImportantInterface被混淆,因此您可以得到: 包中的接口ab.c.dJava 希望在名为a.class的文件中查找包b.c.d中的接口a

类似的规则适用于内部类和接口。

因此,如果你确实混淆了类或接口的定义,则必须在任何地方都提到它混淆的名称。否则,如果例如类MyClass.class被混淆为a.class和另一个类,例如MyClassReference仍然引用此类作为MyClass则当MyClassReference首次尝试使用MyClass时将抛出ClassNotFoundException

关于-Keep @interface *如 ProGuard RefCard 中指定的那样

"keep"可防止删除或重命名类和类成员。

ProGuard RefCard还提到可以使用通配符*

  1. *可用于任意数量的字符(但不能用于包分隔符)
  2. 类名*引用任何类,而不考虑其包。
  3. *匹配任何字段或方法

因此,根据上述定义,-keep @interface *适用于public @interface MyAnnotation {},因为它的名称与通配符*匹配。由于根据定义MyAnnotation不能删除,因此不会从任何地方删除。

相反,-keep class * { @interface <methods>; }更具体,只会保留注释的用法。

要考虑的另一件事是 Keep 后面跟着一个类规范。并基于类规范

@ 规范可用于将类和类成员限制为使用指定注释类型进行批注的类和类成员。指定批注类型就像指定类名一样。

在收缩过程中,pro guard 将删除所有直接或间接使用的方法和成员以及-keep指定的方法和成员。但是,它没有明确提及它对注释的作用。 Pro-Guard提到缩小以下内容:

缺省情况下,将应用收缩;将删除所有类和类成员,但各种 -keep 选项列出的类和类成员以及它们直接或间接依赖的类和类成员除外。 收缩选项 因此,一种情况可能是pro-guard以某种方式检测到使用了注释,并防止其在收缩过程中被删除。 另一种情况是,注释被视为方法的元数据,而不是考虑的成员。 这在 proguard 文档中确实不明显或有很好的记录。

您可以使用-whyareyoukeeping @interface *-verbose从 Prog-Guard 获取有关它保留相关接口的原因的反馈。

更新: 由于上述配置指令的结果是:... is kept by a directive in the configuration.,只能得出结论,-keep @interface *其实。因此,它不提供任何额外的澄清。在对Pro-Guard文档没有任何具体解释的情况下,我认为以下2种可能的解释是可能的: 1. proguard 收缩步骤认为注释用于代码的某些部分,因此需要并且不会减少。 2. class_specification@interface *与注释方法和注释声明匹配。

最新更新