I'm having a problem with ProGuard 4.11 (An application that can optimize, shrink and obfuscate Java code), using the proguard-maven-plugin (github.com/wvengen/proguard-maven-plugin) (Although that shouldn't matter that much, since the error is occurring at runtime and the maven plugin just calls the binary with some arguments as far as I know).
I have an annotation class which is stuctured like this (nothing special):
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD)
public @interface SqlValueCache {
String value();
SqlValueCache.Type type() default Type.OBJECT_UPDATE; //Type is just an ordinary enum
}
I also have some fields annotated with that annotation, but I'm skipping the type()
parameter because I want to use the default value:
@SqlValueCache("nickname")
protected SqlValueHolder<String> nick;
Now I want to process that annotation at runtime:
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
As stated in the comment above, I get an IncompleteAnnotationException
, stating that my annotation declaration is missing the type()
value. But that value should be implied by the default Type.OBJECT_UPDATE
! So now I'm wondering, why is that happening?
I assume that the default
thing is stored in some kind of attribute that I need to specify in -keepattributes
, but I haven't been able to figure out if this is true or which one it is.
It does work just as intended when not using ProGuard.
I have also made sure that the problem is in fact the missing implied value - The code runs as intended when using ProGuard, but explicitly specifying the type()
, like so:
@SqlValueCache(value = "nickname", type = Type.OBJECT_UPDATE)
protected SqlValueHolder<String> nick;
I am using this method as a temporary workaround, but this isn't the prettiest solution in my opinion. Also, as stated above, I still want to know why this error is happening.
Thanks in advance for reading and investigating my question! :)
Yes, I did search the web for solutions and did also use the StackOverflow searchbox. Using the title of this question and various other search queries, I could only find questions complaining about no annotations being kept at all or asking to keep subclasses of classes annotated, etc. I also searched for the exception, but the only useful result was the JavaDoc (docs.oracle.com/javase/7/docs/api/java/lang/annotation/IncompleteAnnotationException.html) of the exception I am encountering.
I'm sorry about the links, but I apparently need 10 reputation to post more than two, although I really like linking stuff :/
I have attached the Stacktrace I got in console (class names won't be useful at all in my opinion - I can attach them if really necessary; My classes are also loaded by a custom class loader, but I doubt that that makes any difference):
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>
(...)
Here's my ProGuard config, should that be of any help (That's the part I find relevant to this question - Full file here: 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);
}
You also need to keep the AnnotationDefault
attribute:
-keepattributes AnnotationDefault
You can get the same effect by changing *Annotations*
to *Annotation*
in your current -keepattributes
option, so the wildcards match AnnotationDefault
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With