I want to keep only classes, which contain methods annotated with @Keep
, and these methods.
These methods (and owning classes) should be kept even if they are unused.
What I write in .pro-file is:
-keepclassmembers class * {
@Keep *;
}
-keepclasseswithmembers class * {
@Keep *;
}
But it shrinks out classes with @Keep methods if they are unused.
Then I try this:
-keep class * {
@Keep *;
}
it just keeps all the classes.
So, what should I write in .pro-file?
Update 1: example Thanks for your answer. But I already use fully-qualified annotation names and include JARs with annotations, but it doesn't do what I want. So, I've prepared a sample.
I have 2 JARs:
example.jar/
example/
code/
more/
A.class
lib.jar/
example/
lib/
Keep.class
A.java:
package example.code.more;
import example.lib.*;
public class A {
@Keep
void foo() {}
}
Keep.java:
package example.lib;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
public @interface Keep {
}
Proguard config, example.pro:
-injars example.jar
-injars lib.jar
-outjars obfuscated.jar
-libraryjars <java.home>/lib/rt.jar
-printmapping rt.map
-renamesourcefileattribute SourceFile
-keepattributes SourceFile,LineNumberTable
-printseeds
-overloadaggressively
-dontoptimize
-keeppackagenames example.lib.**
-keepattributes *Annotation*
-keepclassmembers class * extends java.lang.Enum {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class example.lib.* { *; }
-keep class * extends java.lang.annotation.Annotation { *; }
-keepclassmembers class * {
@example.lib.Keep *;
}
-keepclasseswithmembers class * {
@example.lib.Keep *;
}
See, package names are correct and all the JARs are included.
Resulting map-file:
example.lib.Keep -> example.lib.Keep:
So, A.class gets removed. What am I doing wrong?
-keepclassmembernames. This is the most permissive keep directive; it lets ProGuard do almost all of its work. Unused classes are removed, the remaining classes are renamed, unused members of those classes are removed, but then the remaining members keep their original names.
In Java, you can use access specifiers to protect both a class's variables and its methods when you declare them. The Java language supports four distinct access levels for member variables and methods: private, protected, public, and, if left unspecified, package.
Because in Java, a variable of type abc doesn't contain an abc object. A variable of type abc contains a reference to an abc object. Your reasoning would be valid in say C++. But a class can have static object of self type.
A class declaration can contain static object of self type, it can also have pointer to self type, but it cannot have a non-static object of self type. For example, following program works fine.
Like in examples/annotations/lib/annotations.pro in the ProGuard distribution, you should specify fully qualified names. Furthermore, the option -keepclasseswithmembers doesn't combine well with the "*" wildcard -- use the "<methods>" wildcard instead:
-keepclasseswithmembers class * {
@proguard.annotation.Keep <methods>;
}
You also mustn't forget to read the jar that contains the annotation classes:
-libraryjars annotations.jar
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