Menu

#765 Library interface with generics fails

v6.1
open-works-for-me
None
High
2019-09-09
2019-09-05
No

Hi,

proguard does not recognize interface with gererics in a library. It's implementation method names are then changed.
Attached is a test project.

This interface is in library.jar

public interface MyInterface<T> {
    void setTypedSomething(T var1);

    T getTypedSomething();

    void normalMethod();
}

Implementation class is in in.jar

public class MyImplFail implements MyInterface<MyPojo> {
    MyPojo myPojo;

    public MyImplFail() {
    }

    public void setTypedSomething(MyPojo myPojo) {
        this.myPojo = myPojo;
    }

    public MyPojo getTypedSomething() {
        return this.myPojo;
    }

    public void normalMethod() {
        this.myPojo = null;
    }
}

Proguard result

public final class a implements MyInterface<c> {
    private c a;

    public a() {
    }

    private void a(c var1) {
        this.a = var1;
    }

    private c a() {
        return this.a;
    }

    public final void normalMethod() {
        this.a = null;
    }
}

The problem is the generics. If your implementation uses <object> as a parameter then Proguard works.

public final class b implements MyInterface<Object> {
    private c a;

    public b() {
    }

    public final void setTypedSomething(Object var1) {
        this.a = (c)var1;
    }

    public final Object getTypedSomething() {
        return this.a;
    }

    public final void normalMethod() {
        this.a = null;
    }
}

Thank you,
Martin

</object>
1 Attachments

Discussion

  • Eric Lafortune

    Eric Lafortune - 2019-09-05

    Thanks for your report and test project. The behavior looks correct to me -- how does the problem manifest itself? The name of program class MyPojo is obfuscated to c, and all code is adapted consistently. If you want to prerserve its name (for some external reason), you can specify -keep class MyPojo.

     
  • Eric Lafortune

    Eric Lafortune - 2019-09-05
    • status: open --> open-works-for-me
    • assigned_to: Eric Lafortune
     
  • Martin Jones

    Martin Jones - 2019-09-05

    Hi @lafortune,

    the problem is that methods setTypedSomethingand getTypedSomething got renamed. in implementation.
    The interface is in library jar and therefore we can't rename the implementation methods, right?

    notice that it works fine for method normalMethod.

     
  • Martin Jones

    Martin Jones - 2019-09-05

    Hi @lafortune,

    let me give you an example with a main method.

    public class Main {
        public static void main(String... args) {
            MyInterface<MyPojo> inter = new MyImplFail();
            inter.setTypedSomething(new MyPojo());
            inter.getTypedSomething();
            System.out.println("done");
        }
    }
    

    This code produces output "done" to stdout.

    Now this class obfuscated is:

    public class Main {
        public Main() {
        }
    
        public static void main(String... var0) {
            a var1;
            (var1 = new a()).setTypedSomething(new b());
            var1.getTypedSomething();
            System.out.println("done");
        }
    }
    

    I get the following error

    /SAPDevelop/hybris/proguard_bug/src/Main.java:8: error: cannot find symbol
            (var1 = new a()).setTypedSomething(new b());
                            ^
      symbol:   method setTypedSomething(b)
      location: class a
    
     
  • Eric Lafortune

    Eric Lafortune - 2019-09-09

    If you want to use the processed jar as a library, you have to keep its public API:

    -keep public class * {
        public protected *;
    }
    

    (see the ProGuard manual > Examples > A typical library)

    Do you have a different use case?

    The Java compiler creates two versions of these methods: one with Object and one with the actual type for T.

     
  • Martin Jones

    Martin Jones - 2019-09-09

    hi @lafortune the library jar is not processed at all.
    the bug here is that proguard doesn't evaluate T.
    In the given example proguard should create the version of the method with MyPojo but it doesn't

     

Log in to post a comment.

MongoDB Logo MongoDB