Menu

#536 Support for signature polymorphic methods

v5.0
open-accepted
None
6
2016-09-05
2014-08-20
No

ProGuard doesn't seem to handle "signature polymorphic" methods properly.

The jvm specs (Java SE 7 and 8 Editions) describes "signature polymorphic" methods (§2.9). During method resolution (§5.4.3.3) " If [the class] declares exactly one method with the name specified by the method reference, and the declaration is a signature polymorphic method (§2.9), then method lookup succeeds."

How to reproduce:

$ cat Test.java
public class Test {
  public void foo(java.lang.invoke.MethodHandle m) throws Throwable {
    m.invokeExact(1,2,3);
  }
}
$ java -version
openjdk version "1.8.0_11"
OpenJDK Runtime Environment (build 1.8.0_11-b12)
OpenJDK 64-Bit Server VM (build 25.11-b02, mixed mode)
$ javac Test.java
$ java -jar proguard-5.0.jar -injar Test.class -libraryjar rt.jar
ProGuard, version 5.0
Reading program directory [Test.class]
Reading library jar [rt.jar]
Warning: Test: can't find referenced method 'void invokeExact(int,int,int)' in library class java.lang.invoke.MethodHandle
Warning: there were 1 unresolved references to library class members.
         You probably need to update the library versions.
         (http://proguard.sourceforge.net/manual/troubleshooting.html#unresolvedlibraryclassmember)

Error: Please correct the above warnings first.

Discussion

  • Eric Lafortune

    Eric Lafortune - 2014-08-20

    Thanks for the concise report. ProGuard currently doesn't treat MethodHandle#invoke/invokeExact differently from regular methods, so you'll see this warning. As you probably know, it is generally not possible to figure out to which method or methods the invocation should be linked, with static analysis and even with dynamic analysis. Dynamic invocations are a real pain for static analysis and optimizations. The warning can help as a reminder that you may need to preserve the targeted methods with this given signature. In the extreme, you could preserve all matching methods, e.g. in this case:

    -keepclassmembers class * {
        void *(int, int, int);
    }
    

    You can suppress the warning with

    -dontwarn java.lang.invoke.MethodHandle
    

    ProGuard should probably provide a more accurate warning for this particular case. I'll consider it. Your thoughts are welcome.

     
  • Eric Lafortune

    Eric Lafortune - 2014-08-20
    • status: open --> open-accepted
    • assigned_to: Eric Lafortune
    • Priority: 5 --> 6
     
  • Gilles Duboscq

    Gilles Duboscq - 2014-08-21

    Indeed, don't think that making a note for each method that matches the signature can scale very well but a customized warning mentioning the signature that is used would definitely help.

    Thank you for the quick answer.

     
  • Gilles Duboscq

    Gilles Duboscq - 2014-09-04

    A more severe issue is that the types in the signature that is used at the invoke point of the signature polymorphic method are not rewritten/obfuscated properly.

     
  • Trejkaz

    Trejkaz - 2016-09-05

    Another issue going on here is that ProGuard is calling this a "warning", but then failing. I'm pretty sure that it's misunderstanding the meaning of "warning".

     
    • Eric Lafortune

      Eric Lafortune - 2016-09-05

      ProGuard has three types of messages: notes, warnings, and errors. Notes are suggestions, e.g. about probable typos. Errors are fatal problems, e.g. I/O errors. Warnings are the class of problems inbetween, e.g. missing dependencies. A compiler would fail on them, but with ProGuard you can suppress them with -ignorewarnings or -dontwarn.

       

Log in to post a comment.