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

MethodHandleProxies does not correctly identify single-method interfaces

    XMLWordPrintable

Details

    • Bug
    • Resolution: Duplicate
    • P4
    • None
    • 7
    • hotspot
    • None
    • x86
    • linux

    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).

      Attachments

        Issue Links

          Activity

            People

              jrose John Rose
              briangoetz Brian Goetz
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: