When every interface is compiled, even with proguard, it should create a valid class file that can be used in the java virtual machine.
Java has specific naming rules for connecting interfaces and classes in packages with the files.
So for example even if interface VeryImportantInterface
of package com.mycompany.mypackage
is obfuscated and as a result you get:
interface a
in package b.c.d
java expects to find interface a
in package b.c.d
in a file named a.class
Similar rules apply for inner classes and interfaces.
So if you do obfuscate the definition of a class or interface, it will have to be mentioned everywhere with its obfuscated name.Otherwise if for example class MyClass.class
is obfuscated to a.class
and another class, e.g. MyClassReference
still references this class as MyClass
then a ClassNotFoundException
will be thrown when MyClassReference
attempts to use MyClass
for the first time.
Regarding -keep @interface *
As specified in ProGuard RefCard
'keep' prevents classes and class members from being removed or renamed.
ProGuard RefCard also mentions that wildcard *
can be used
*
can be used for any number of characters (but not the package separator)
- the class name
*
refers to any class, irrespective of its package.
*
matches any field or method
So -keep @interface *
according to the definitions above applies to public @interface MyAnnotation {}
since its name match the wildcard *
. Since according to the definition MyAnnotation
is not to be removed, it is not removed from anywhere.
On the contrary -keep class * { @interface <methods>; }
is more specific and would keep only the usages of the annotation.
Another thing to consider is that keep is followed by a Class specification. And based on the Class specification
The @ specifications can be used to restrict classes and class members to the ones that are annotated with the specified annotation types. An annotationtype is specified just like a classname.
During the shrinking process pro guard will delete all the methods and members that are directly or indirectly used plus the ones specified by -keep
. However it does not explicitly mention what it does with annotations.
Pro-Guard mentions regarding shrinking the following:
By default, shrinking is applied; all classes and class members are removed, except for the ones listed by the various -keep options, and the ones on which they depend, directly or indirectly.
Shrinking Options
So one case could be that pro-guard somehow detects that the annotation is used and prevents it from beeing removed during shrinking.
Another case would be that the annotations are considered metadatum of the methods and not beeing considered members.
It is really not obvious or well documented in proguard documentation.
You can use -whyareyoukeeping @interface *
and -verbose
to get a feedback from Prog-Guard on why it is keeping the related interfaces.
Update:
Since the result of the above configuration directives was:
... is kept by a directive in the configuration.
, it can only be concluded that the -keep @interface *
actually . Hence it is does not provide any additional clarification. Without any specific explanation on the Pro-Guard documentation I think the following 2 possible explanations are possible:
1. The proguard shrinking step considers that the annotation is used in some part of the code, thus needed and is not reduced.
2. The class_specification @interface *
matches both annotated methods and annotation declarations.
-keep @interface *
should really only apply to where annotations are defined like your examplepublic @interface MyAnnotation {}
-- but the whole point of my question is that this isn't what's actually happening. This-keep @interface *
command is keeping annotations where they're used (please reread my original post for more context). I'm trying to understand why. – Recurrence