Menu

#734 Proguard occasionally breaks guava Function.apply java8 bytecode

v6.0
closed-fixed
None
Medium
2019-05-14
2018-11-22
No

More details available here:

https://issuetracker.google.com/issues/119182681

When not desugaring before Proguard, dropbox are seeing that the Proguarded jar contains an invokedynamic instruction saying that a lambda class with an 'apply' method should be generated. However, the on the functional interface in question (guava Function interface) the 'apply' method has been renamed to 'a'.

It therefore looks like there are cases where Proguard renames an interface method, but does not rename the implementation method in invokedynamic instructions that mention that interface method.

Anynomyzed code after proguard

public final boolean d();
    descriptor: ()Z
    flags: ACC_PUBLIC, ACC_FINAL
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: getfield      #44                 // Field h:Lsome/class;
         4: invokevirtual #78                 // Method some.class.a:()Ljava/lang/Object;
         7: checkcast     #25                 // class com/google/common/base/l
        10: invokedynamic #114,  0            // InvokeDynamic #1:apply:()Lcom/google/common/base/h;
        15: invokevirtual #89                 // Method com/google/common/base/l.a:(Lcom/google/common/base/h;)Lcom/google/common/base/l;
        18: iconst_0
        19: invokestatic  #99                 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
        22: invokevirtual #90                 // Method com/google/common/base/l.a:(Ljava/lang/Object;)Ljava/lang/Object;
        25: checkcast     #29                 // class java/lang/Boolean
        28: invokevirtual #98                 // Method java/lang/Boolean.booleanValue:()Z
        31: ireturn
      LineNumberTable:
        line 138: 0

Notice the invokedynamic at offset 10 which uses the name apply, but the invoke-virtual after it calls the method 'a'. Looking at com/google/common/base/h we see that this is the Function interface where apply has been renamed to a:

Classfile h.class
  Last modified Nov 21, 2018; size 293 bytes
  MD5 checksum 17cd2735d44082a6d07262e7cdf35564
  Compiled from "SourceFile"
public interface com.google.common.base.h<F extends java.lang.Object, T extends java.lang.Object>
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
Constant pool:
   #1 = Class              #10            // com/google/common/base/h
   #2 = Class              #12            // java/lang/Object
   #3 = Utf8               (Ljava/lang/Object;)Ljava/lang/Object;
   #4 = Utf8               (Ljava/lang/Object;)Z
   #5 = Utf8               (TF;)TT;
   #6 = Utf8               <F:Ljava/lang/Object;T:Ljava/lang/Object;>Ljava/lang/Object;
   #7 = Utf8               Signature
   #8 = Utf8               SourceFile
   #9 = Utf8               a
  #10 = Utf8               com/google/common/base/h
  #11 = Utf8               equals
  #12 = Utf8               java/lang/Object
{
  public abstract T a(F);
    descriptor: (Ljava/lang/Object;)Ljava/lang/Object;
    flags: ACC_PUBLIC, ACC_ABSTRACT
    Signature: #5                           // (TF;)TT;

  public abstract boolean equals(java.lang.Object);
    descriptor: (Ljava/lang/Object;)Z
    flags: ACC_PUBLIC, ACC_ABSTRACT
}
Signature: #6                           // <F:Ljava/lang/Object;T:Ljava/lang/Object;>Ljava/lang/Object;
SourceFile: "SourceFile"

Discussion

  • Eric Lafortune

    Eric Lafortune - 2018-11-27

    Thanks for your report. Invokedynamic is pretty messy. We could reproduce the issue and we've now fixed it for the upcoming ProGuard 6.1.0 beta2.

     
  • Eric Lafortune

    Eric Lafortune - 2018-11-27
    • status: open --> open-fixed
    • assigned_to: Eric Lafortune
     
  • Eric Lafortune

    Eric Lafortune - 2019-05-14
    • Status: open-fixed --> closed-fixed
     

Log in to post a comment.