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

Multiply-bound generic parameters do not produce correct lambda bootstrap method instantiatedMethodType parameter

XMLWordPrintable

    • x86

      FULL PRODUCT VERSION :
      java version "1.8.0_121"
      Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
      Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows [Version 6.1.7601]

      A DESCRIPTION OF THE PROBLEM :
      For variables of a bound-type, where the type is multiply-bound eg. <E extends X & Y>, using method references for the second type does not produce the correct instantiedMethodType bootstrap method argument.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      # Run the test method of the following code after compiling with javac, using TestNG. Alternatively, the TestNG code can be removed, with the apply method being called directly.


      package com.example;

      import static java.util.Optional.ofNullable;
      import static org.testng.Assert.assertEquals;

      import java.util.function.Supplier;

      import org.testng.annotations.Test;

      public class MultiplyBoundMethodReferenceBug
      {
          public enum ValuedEnum implements Supplier<String>
          {
              ONE_HUNDRED( "100" );

              private final String myValue;

              private ValuedEnum( final String value )
              {
                   myValue = value;
              }

              @Override
              public String get()
              {
                  return myValue;
              }
          }

          private static <E extends Enum<E> & Supplier<?>> Object apply( final E e )
          {
              return ofNullable( e )
                         .map( Supplier::get )
                         .orElse( null );
          }

          @Test
          public void test() throws Exception
          {
              assertEquals( apply( ValuedEnum.ONE_HUNDRED ), "100" );
          }
      }

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Expected the test to pass.

      Expected the following instantiated method type signature in the invokedynamic instruction generated for Supplier::get

      (Ljava/util/function/Supplier;)Ljava/lang/Object;
      ACTUAL -
      Received the following stack trace:

      java.lang.BootstrapMethodError: call site initialization exception
      at java.lang.invoke.CallSite.makeSite(CallSite.java:341)
      at java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(MethodHandleNatives.java:307)
      at java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:297)
      at com.example.MultiplyBoundMethodReferenceBug.apply(MultiplyBoundMethodReferenceBug.java:34)
      at com.example.MultiplyBoundMethodReferenceBug.test(MultiplyBoundMethodReferenceBug.java:41)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:498)
      at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
      at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
      at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
      at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
      at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
      at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
      at org.testng.TestRunner.privateRun(TestRunner.java:767)
      at org.testng.TestRunner.run(TestRunner.java:617)
      at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
      at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
      at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
      at org.testng.SuiteRunner.run(SuiteRunner.java:240)
      at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
      at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
      at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
      at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
      at org.testng.TestNG.run(TestNG.java:1057)
      at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:132)
      at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:236)
      at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:81)
      Caused by: java.lang.invoke.LambdaConversionException: Invalid receiver type class java.lang.Enum; not a subtype of implementation type interface java.util.function.Supplier
      at java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:233)
      at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:303)
      at java.lang.invoke.CallSite.makeSite(CallSite.java:302)
      ... 28 more

      Saw the following instantiated method type signature in the invokedynamic instruction generated for Supplier::get

      (Ljava/lang/Enum;)Ljava/lang/Object;

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      java.lang.BootstrapMethodError: call site initialization exception
      at java.lang.invoke.CallSite.makeSite(CallSite.java:341)
      at java.lang.invoke.MethodHandleNatives.linkCallSiteImpl(MethodHandleNatives.java:307)
      at java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:297)
      at com.example.MultiplyBoundMethodReferenceBug.apply(MultiplyBoundMethodReferenceBug.java:34)
      at com.example.MultiplyBoundMethodReferenceBug.test(MultiplyBoundMethodReferenceBug.java:41)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at java.lang.reflect.Method.invoke(Method.java:498)
      at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
      at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
      at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
      at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
      at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
      at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
      at org.testng.TestRunner.privateRun(TestRunner.java:767)
      at org.testng.TestRunner.run(TestRunner.java:617)
      at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
      at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
      at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
      at org.testng.SuiteRunner.run(SuiteRunner.java:240)
      at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
      at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
      at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
      at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
      at org.testng.TestNG.run(TestNG.java:1057)
      at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:132)
      at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:236)
      at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:81)
      Caused by: java.lang.invoke.LambdaConversionException: Invalid receiver type class java.lang.Enum; not a subtype of implementation type interface java.util.function.Supplier
      at java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:233)
      at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:303)
      at java.lang.invoke.CallSite.makeSite(CallSite.java:302)
      ... 28 more

      REPRODUCIBILITY :
      This bug can be reproduced rarely.

      ---------- BEGIN SOURCE ----------
      package com.example;

      import static java.util.Optional.ofNullable;
      import static org.testng.Assert.assertEquals;

      import java.util.function.Supplier;

      import org.testng.annotations.Test;

      public class MultiplyBoundMethodReferenceBug
      {
          public enum ValuedEnum implements Supplier<String>
          {
              ONE_HUNDRED( "100" );

              private final String myValue;

              private ValuedEnum( final String value )
              {
                   myValue = value;
              }

              @Override
              public String get()
              {
                  return myValue;
              }
          }

          private static <E extends Enum<E> & Supplier<?>> Object apply( final E e )
          {
              return ofNullable( e )
                         .map( Supplier::get )
                         .orElse( null );
          }

          @Test
          public void test() throws Exception
          {
              assertEquals( apply( ValuedEnum.ONE_HUNDRED ), "100" );
          }
      }
      ---------- END SOURCE ----------

            fmatte Fairoz Matte
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: