Lambda and JSR 292 method handle

Howard Lovatt howard.lovatt at iee.org
Fri Dec 18 07:06:58 PST 2009


I don't get what you are saying, probably just me being slow, so
please bare with me. If in compilation unit A I have:

void m( #int(int) f ) { out.println( f( 2 ); }

and I use MethodHandle then this will get translated into:

void m( MethodHandle f ) { out.println( f.<int>invokeGeneric( 2 ) ); }

Then in compilation unit B I will see the signature "void m(
MethodHandle )", i.e. the actual types have been erased. In
compilation unit B I can therefore say:

m( #void() );

and the compiler will allow this because in compilation unit B it
doesn't know that m really expects a #int(int) because that
information was lost when the function type was converted to a
MethodHandle which carries only type information at runtime not
compiletime.

What am I missing?

Thanks,

 -- Howard.

2009/12/18 Rémi Forax <forax at univ-mlv.fr>:
> Le 18/12/2009 11:55, Howard Lovatt a écrit :
>>
>> Rémi,
>>
>> I thought the idea from the JSR 292 group was to use JavaMethodHandle
>> [1] (which extends MethodHandle). The difference is that the
>> JavaMethodHandle retains the type information, needed by Java, and it
>> can implement interfaces so you can use a lambda with an existing
>> function. Your example:
>>
>> class A {
>>    public static void main(String[] args) {
>>      #int(int) f = #(int x) (x+x);
>>      f(2);
>>    }
>> }
>>
>
> Here is what I am thinking:
> A JavaMethodHandle is a method handle that allow you to implement one or
> more interface.
> One goal is to use it to implement function conversion, i.e when you want to
> use a lambda
> as a class implementing an interface like Runnable, Callable, etc to be able
> to use legacy code.
> Because a JavaMethodHandle is a method handle, you don't need an interface
> like CallableInitInt,
> you already can invoke it using .invokeLambda().
>
> This approach is too heavyweight for being used for 'classical' lambda
> because it requires
> to create a new class for each lambda.
>
> Some experts in JSR 292 expert group think that JavaMethodHandle aren't
> neccessary.
> They complexify the implementation and may disable some optimizations done
> by the VM.
> So this feature is still under consideration.
>
> You can notice that function conversion (the one of the strawman proposal
> and the one of BGGA)
> doesn't require that the resulting object to be a lambda.
>
> Runnable r = #() { System.out.println("run"); }
> #void() f = (#void()) r;    // works with JavaMethodHandle but not required
> by the spec
>
> So function conversion can be implemented without JavaMethodHandle.
>
> Cheers,
> Rémi
>
>> Would get translated to:
>>
>> class A {
>>   private static final class Lambda$1 extends JavaMethodHandle
>> implements CallableIntInt {
>>     private static final Lambda$1 instance = new Lambda$1();
>>     @Override public int call( int x ) { return x + x; }
>>     private Lambda$1() { super "CALL"; }
>>     private static final MethodHandle CALL =
>> MethodHandles.lookup().findVirtual( Lambda$1.class, "call",
>> MethodHandles.methodType( int.class, int.class ) );
>>   }
>>   public static void main(String[] args) {
>>     CallableIntInt f = Lambda$1.instance;
>>     f.call(2);
>>   }
>> }
>>
>> Where CallableIntInt is either a standard interface, in java.lang say,
>> or a synthetic interface (depending on implementation details) and is:
>>
>> public interface CallableIntInt { int call( int a ); }
>>
>> If you use a MethodHandle directly then you can't pass it to anything
>> because you have lost the type information, i.e. an invokeGeneric on a
>> method handle will accept any arguments (though will throw a runtime
>> exception). EG if I have a method:
>>
>> void m( #int(int) f ) { out.println( f( 2 ) ); }
>>
>> Then if you use MethodHandles directly it would be translated to:
>>
>> void m( MethodHandle f ) { out.println( f.<int>invokeGeneric( 2 ) ); }
>>
>> But then I could say:
>>
>> m( #void() () );
>>
>> And the compiler couldn't catch the mistake. Using JavaMethodHandles
>> instead, would mean m is translated into:
>>
>> void m( CallableIntInt f ) { out.println( f.call( 2 ) ); }
>>
>> And hence retains type safety.
>>
>> The above JavaMethodHandle version doesn't seem to be that much better
>> than using an inner class directly! There was also, at least
>> originally, talk of anonymous classes in JSR 292 [2]; these would seem
>> to be more useful, are they still part of JSR 292? (I ask because I
>> think you are on the expert group.)
>>
>>   -- Howard.
>>
>> PS The above APIs are in a state of flux, I have used the versions (at
>> least I tried to without having a compiler to check my code) from the
>> paper you can download from [3].
>>
>> Ref:
>> [1] http://cr.openjdk.java.net/~jrose/pres/indy-javadoc-b59/
>> [2] http://blogs.sun.com/jrose/resource/DVMTest.java.txt
>> [3] http://blogs.sun.com/jrose/entry/vmil_paper_on_invokedynamic
>>
>
>
> ______________________________________________________________________
> This email has been scanned by the MessageLabs Email Security System.
> For more information please visit http://www.messagelabs.com/email
> ______________________________________________________________________
>



-- 
  -- Howard.


More information about the lambda-dev mailing list