JDK-8028739 : javac generates incorrect descriptor for MethodHandle::invoke
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8
  • Priority: P2
  • Status: Closed
  • Resolution: Fixed
  • Submitted: 2013-11-20
  • Updated: 2018-05-21
  • Resolved: 2013-11-23
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8
8 b119Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
Invocations of signature polymorphic methods (MethodHandle.invoke, MethodHandle.invokeExact) derive the bytecode descriptor of the method call from the call site rather than the method's declared signature ("([Ljava/lang/Object;)Ljava/lang/Object;").  See JLS 15.12.3.

A method handle like MethodHandle::invoke or mh::invoke should do the same.  But currently, the descriptor generated by javac always seems to be "([Ljava/lang/Object;)Ljava/lang/Object;".

Test case:

---
import java.lang.invoke.*;

public class MHInvoke {

  interface TriFunction {
      Object apply(String a, char b, char c) throws Throwable;
  }

  public static void main(String... args) throws Throwable {
      MethodHandles.Lookup lookup = MethodHandles.lookup();
      MethodType mt = MethodType.methodType(String.class, char.class, char.class);
      MethodHandle ms = lookup.findVirtual(String.class, "replace", mt);

      System.out.println("result 1: " + ms.invoke("some string to search", 's', 'o'));
      
      TriFunction f1 = (a, b, c) -> ms.invoke(a,b,c);
      System.out.println("result 2: " + f1.apply("some string to search", 's', 'o'));
      
      TriFunction f2 = ms::invoke;
      System.out.println("result 3: " + f2.apply("some string to search", 's', 'o'));
  }
}

---

Expected: Run successfully
Actual: BootstrapMethodError

---

Looking at the bytecode, here's the 'invoke' call from the lambda body:

         4: invokevirtual #15                 // Method java/lang/invoke/MethodHandle.invoke:(Ljava/lang/String;CC)Ljava/lang/Object;

And here's the 'invoke' call for the method reference (passed as an argument to 'metafactory' in the form of a MethodHandle):

        #74 invokevirtual java/lang/invoke/MethodHandle.invoke:([Ljava/lang/Object;)Ljava/lang/Object;

This should look like the following instead:

        #74 invokevirtual java/lang/invoke/MethodHandle.invoke:(Ljava/lang/String;CC)Ljava/lang/Object;

Comments
I think this is more in Robert's area, reassigning it.
20-11-2013

Note that the fact that the descriptor for the method reference is derived from the types of the parameters of the targeted function type is implied, but not completely spelled out. See Lambda Spec bug JDK-8028690.
20-11-2013