JDK-8175128 : Multiply-bound generic parameters do not produce correct lambda bootstrap method instantiatedMethodType parameter
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8u121
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • CPU: x86
  • Submitted: 2017-02-16
  • Updated: 2019-08-02
  • Resolved: 2017-02-17
Related Reports
Duplicate :  
Description
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 ----------


Comments
This is duplicate issue of JDK-8142476 which has been fixed in 9
17-02-2017