Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proguard removes overridden methods in abstract class as unused

Tags:

java

proguard

Proguard is removing the overridden methods in an abstract class as unused, even though they are used in the parent class. Here is a reference implementation showing the behaviour

public abstract class Animal {
    Animal() {
        born();
    }

    abstract void born();
}

public abstract class Human extends Animal {
    @Override
    void born() {
        System.out.println("Human is born.");
    }
}

The keep attributes are defined as:

-keep public class test.Human {
    public *;
}

Proguard removes the overridden born() methods in Human class as unused, even though it is used from the constructor of Animal class. The resulting mapping file is

test.Animal -> test.a:
    void born() -> a
test.Human -> test.Human:

This problem does not exist if the class Human is not abstract. If the class Human is non-abstract, the resulting mapping file is

test.Animal -> test.a:
    void born() -> a
test.Human -> test.Human:
    void born() -> a

As we can see, the method born() is retained in this case.

Is this a bug in proguard? Or is there any optimization setting that can provide the desired behaviour?

I am using proguard with android studio.

like image 926
Adwiv Avatar asked May 22 '15 15:05

Adwiv


2 Answers

You configure ProGuard to keep public methods, while born() is package private. Your configuration should rather be like this.

-keep public class test.Human {
    <methods>;
}

It will keep all package private (default) methods of Human class.

If you want to keep methods but still allow obfuscation for them, you can use something like this:

-keep, allowobfuscation public class test.Human {
    <methods>;
}
like image 105
sergej shafarenka Avatar answered Oct 18 '22 13:10

sergej shafarenka


Since the problem only manifests when these classes are part of a library (and without any concrete implementation within the library), I took the easy way out and added -dontshrink to retain (with obfuscation) all the classes and methods.

In most cases; class and method shrinking need not be done when releasing a library.

Still I believe it is a bug in usage graph to ignore the overridden method implementations. I have filed a bug in the proguard bug tracker. https://sourceforge.net/p/proguard/bugs/574/

like image 40
Adwiv Avatar answered Oct 18 '22 14:10

Adwiv