JDK-7148356 : MethodHandleProxies does not correctly identify single-method interfaces
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 7
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: linux
  • CPU: x86
  • Submitted: 2012-02-23
  • Updated: 2012-02-24
  • Resolved: 2012-02-24
Related Reports
Duplicate :  
Description
The class MethodHandleProxies performs a conversion from a method handle to an instance of a single-method interface.  However, in the presence of bridge methods generated by javac, MethodHandleProxies does not correctly identify when two methods with distinct signatures in the classfile correspond to the same Java method.  

Following is a TestNG test case that reproduces the problem; test cases test1 and test2 pass, but test3 fails with the following error:

java.lang.IllegalArgumentException: not a single-method interface: regressions.bridgesam.StringFactory2
	at java.lang.invoke.MethodHandleProxies.asInterfaceInstance(MethodHandleProxies.java:140)
	at regressions.bridgesam.BridgeSams.test3(BridgeSams.java:34)


public interface ObjectFactory<T> {
    public T make();
}

public interface StringFactory1 extends ObjectFactory<String> {
}

public interface StringFactory2 extends ObjectFactory<String> {
    public String make();
}

@Test
public class BridgeSams {
    public static String make() {
        return "wooga";
    }

    public void test1() throws NoSuchMethodException, IllegalAccessException {
        MethodHandle mh = MethodHandles.lookup().findStatic(BridgeSams.class, "make", MethodType.methodType(String.class));
        ObjectFactory<String> of = MethodHandleProxies.asInterfaceInstance(ObjectFactory.class, mh);
        assertEquals("wooga", of.make());
    }

    public void test2() throws NoSuchMethodException, IllegalAccessException {
        MethodHandle mh = MethodHandles.lookup().findStatic(BridgeSams.class, "make", MethodType.methodType(String.class));
        StringFactory1 of = MethodHandleProxies.asInterfaceInstance(StringFactory1.class, mh);
        assertEquals("wooga", of.make());
    }

    public void test3() throws NoSuchMethodException, IllegalAccessException {
        MethodHandle mh = MethodHandles.lookup().findStatic(BridgeSams.class, "make", MethodType.methodType(String.class));
        StringFactory2 of = MethodHandleProxies.asInterfaceInstance(StringFactory2.class, mh);
        assertEquals("wooga", of.make());
    }
}

The difference between StringFactory1 and StringFactory2 is that StringFactory2 explicitly names the specialized signature (substituting String for T in ObjectFactory<T>).  

This bug will likely affect all functional interface types that use bridge methods (covariant returns and/or generic parameter substitution).

Comments
EVALUATION Fixed as part of 7054590 in 7u2 and 8.
24-02-2012