java - ProGuard 忽略注释默认值

标签 java annotations proguard

问题

我遇到了 ProGuard 的问题4.11(一个可以优化、收缩和混淆 Java 代码的应用程序),使用 proguard-maven-plugin (github.com/wvengen/proguard-maven-plugin)据我所知,在运行时和 Maven 插件只调用带有一些参数的二进制文件)。

我有一个注释类,其结构如下(没什么特别的):

@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD)
public @interface SqlValueCache {
  String value();

  SqlValueCache.Type type() default Type.OBJECT_UPDATE; //Type is just an ordinary enum
}

我也有一些用该注释注释的字段,但我跳过了 type() 参数,因为我想使用默认值:

 @SqlValueCache("nickname")
 protected SqlValueHolder<String> nick;

现在我想在运行时处理该注解:

SqlValueCache annotation = field.getAnnotation(SqlValueCache.class); //Skipped the validation
annotation.value(); //Works fine, because specified
annotation.type(); //java.lang.annotation.IncompleteAnnotationException, *not* using the default

如上面的评论所述,我得到一个 IncompleteAnnotationException,表明我的注释声明缺少 type() 值。但是该值应该由 default Type.OBJECT_UPDATE 隐含! 所以现在我想知道,为什么会这样?

假设

我假设 default 存储在我需要在 -keepattributes 中指定的某种属性中,但我无法确定是否这是真的还是哪一个。

复制

在不使用 ProGuard 时,它确实按预期工作。

我还确定问题实际上是缺少隐含值 - 使用 ProGuard 时代码按预期运行,但显式指定 type(),如下所示:

 @SqlValueCache(value = "nickname", type = Type.OBJECT_UPDATE)
 protected SqlValueHolder<String> nick;

我将此方法用作临时解决方法,但在我看来这不是最漂亮的解决方案。另外,如上所述,我仍然想知道为什么会发生此错误。

提前感谢您阅读和调查我的问题! :)

附录/元

是的,我确实在网上搜索了解决方案,也确实使用了 StackOverflow 搜索框。使用这个问题的标题和其他各种搜索查询,我只能找到提示根本没有保留注释或要求保留类的子类注释等的问题。我还搜索了异常,但唯一有用的结果是我遇到的异常的 JavaDoc (docs.oracle.com/javase/7/docs/api/java/lang/annotation/IncompleteAnnotationException.html)。

对于链接,我很抱歉,但我显然需要 10 个声誉才能发布两个以上,尽管我真的很喜欢链接的东西:/

堆栈跟踪

我已经附加了我在控制台中获得的 Stacktrace(我认为类名根本没有用 - 如果真的有必要,我可以附加它们;我的类也由 custom class loader 加载,但我怀疑有什么区别):

java.lang.ExceptionInInitializerError
at <class with annotated field>
(...)
Caused by: java.lang.annotation.IncompleteAnnotationException: io.github.xxyy.common.sql.builder.annotation.SqlValueCache missing element type
at sun.reflect.annotation.AnnotationInvocationHandler.invoke(AnnotationInvocationHandler.java:72) ~[?:1.7.0_51]
at com.sun.proxy.$Proxy18.type(Unknown Source)
at <line accessing type() of SqlValueCache>
(...)

混淆器配置

这是我的 ProGuard 配置,它是否有帮助(这是我发现与这个问题相关的部分 - 完整文件在这里:pastebin.com/u6wt00cj):

-dontskipnonpubliclibraryclassmembers
-target 1.7
-dontshrink
-dontoptimize
-repackageclasses io.github.xxyy.obf.towerdefense.client
-keepattributes SourceFile,LineNumberTable,*Annotations*,LocalVariable*Table

-keep,allowobfuscation class ** {
    <fields>;
    <methods>;
}

-keep,allowshrinking class **.annotation** {
    <fields>;
    <methods>;
}

# Also keep - Enumerations. Keep the special static methods that are required in
# enumeration classes.
-keepclassmembers enum  ** {
  public static **[] values();
  public static ** valueOf(java.lang.String);
}

最佳答案

您还需要保留 AnnotationDefault 属性:

-keepattributes AnnotationDefault

您可以通过在当前的 -keepattributes 选项中将 *Annotations* 更改为 *Annotation* 来获得相同的效果,因此通配符匹配AnnotationDefault.

关于java - ProGuard 忽略注释默认值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23122780/

相关文章:

java - proguard 可以忽略库中未使用的类吗?

java - TalenD 中的 .item 和 .properties 文件有何用途?

java - MappedBy 引用未知目标实体属性两次?

java - Spark `FileAlreadyExistsException` when `saveAsTextFile` 即使输出目录不存在

java - 这是对基于 Java 的 Web 应用程序中 404 和 50 的滥用修复吗?

java - 如何在没有快速调用的情况下处理任何实例上的注释

java - 如何实例化一个类 "annotation processed"?

java - 使用 Shiro 、 NullPointerException 时对 Spring 进行注释

android - 在哪里可以找到 `Warnings found during shrinking` 的警告?

android - 混淆时是否需要在混淆规则中使用 'keep' Parcelable