title: Explicit use of LambdaMetafactory
body: <p>I'm trying to explicitly use LambdaMetafactory.metafactory, I can't understand why it works only with the Runnable functional interface. For Example, this code does what it is expected (it prints &quot;hello world&quot;):</p>
  <pre><code>public class MetafactoryTest {
      
      public static void main(String[] args) throws Throwable {
  
          MethodHandles.Lookup caller = MethodHandles.lookup();
          MethodType methodType = MethodType.methodType(void.class);
          MethodType invokedType = MethodType.methodType(Runnable.class);
          CallSite site = LambdaMetafactory.metafactory(caller, 
                                                        &quot;run&quot;, 
                                                        invokedType, 
                                                        methodType, 
                                                        caller.findStatic(MetafactoryTest.class, &quot;print&quot;, methodType), 
                                                        methodType);
          MethodHandle factory = site.getTarget();
          Runnable r = (Runnable) factory.invoke();
          r.run();
      }
      
      private static void print() {
          System.out.println(&quot;hello world&quot;); 
      }    
  }
  </code></pre>
  <p>The problem arises when I try to use a different functional interface, such as Supplier. The following code does not work:</p>
  <pre><code>public class MetafactoryTest {
  
      public static void main(String[] args) throws Throwable {
  
          MethodHandles.Lookup caller = MethodHandles.lookup();
          MethodType methodType = MethodType.methodType(String.class);
          MethodType invokedType = MethodType.methodType(Supplier.class);
          CallSite site = LambdaMetafactory.metafactory(caller, 
                                                        &quot;get&quot;, 
                                                        invokedType, 
                                                        methodType, 
                                                        caller.findStatic(MetafactoryTest.class, &quot;print&quot;, methodType), 
                                                        methodType);
          MethodHandle factory = site.getTarget();
          Supplier&lt;String&gt; r = (Supplier&lt;String&gt;) factory.invoke();
          System.out.println(r.get());        
      }
      private static String print() {
          return &quot;hello world&quot;;
      }    
  }
  
  
  Exception in thread &quot;main&quot; java.lang.AbstractMethodError: metafactorytest.MetafactoryTest$$Lambda$1/258952499.get()Ljava/lang/Object;
      at metafactorytest.MetafactoryTest.main(MetafactoryTest.java:29)
  </code></pre>
  <p>Shouldn't the two snippets of code work in a similar way, what is the problem in the second one?</p>
  <p>Moreover, the following code which should be equivalent, works well:</p>
  <pre><code>public class MetafactoryTest {
  
      public static void main(String[] args) throws Throwable {
          Supplier&lt;String&gt; r = (Supplier&lt;String&gt;) () -&gt; print();
          System.out.println(r.get());        
      }
  
      private static String print() {
          return &quot;hello world&quot;;
      }    
  }
  </code></pre>
  <p><strong>Edit</strong></p>
  <p>Another solution that avoids changing the method return type is to define a new functional interface:</p>
  <pre><code>public class MetafactoryTest {
  
      @FunctionalInterface
      public interface Test {
          String getString();
      }
      
      public static void main(String[] args) throws Throwable {
  
          MethodHandles.Lookup caller = MethodHandles.lookup();
          MethodType methodType = MethodType.methodType(String.class);
          MethodType invokedType = MethodType.methodType(Test.class);
          CallSite site = LambdaMetafactory.metafactory(caller, 
                                                        &quot;getString&quot;, 
                                                        invokedType, 
                                                        methodType, 
                                                        caller.findStatic(MetafactoryTest.class, &quot;print&quot;, methodType), 
                                                        methodType);
          MethodHandle factory = site.getTarget();
          Test r = (Test) factory.invoke();
          System.out.println(r.getString());        
      }
      
      private static String print() {
          return &quot;hello world&quot;;
      }  
  </code></pre>