Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8028739

javac generates incorrect descriptor for MethodHandle::invoke

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P2
    • Resolution: Fixed
    • Affects Version/s: 8
    • Fix Version/s: 8
    • Component/s: tools
    • Subcomponent:
    • Resolved In Build:
      b119
    • Verification:
      Verified

      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;

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                rfield Robert Field
                Reporter:
                dlsmith Dan Smith
              • Votes:
                0 Vote for this issue
                Watchers:
                3 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: