ProGuard忽略注释默认值

时间:2014-04-17 00:56:16

标签: 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配置

这是我的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);
}

1 个答案:

答案 0 :(得分:3)

您还需要保留AnnotationDefault属性:

-keepattributes AnnotationDefault

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