Boxing function types
Fredrik O"hrstro"m
fredrik.ohrstrom at oracle.com
Tue Nov 24 01:20:46 PST 2009
Neal Gafter skrev:
> Kochurov-
>
> This is an interesting idea, but you have the variance backwards for
> argument types. The argument types in the function on the
> right-hand-side of the assignment must be subtypes (not supertypes) of
> the argument types in the function on the left-hand-side.
>
This is in fact MethodHandle.invokeGeneric
For those not following the JSR292 mailing list, the MethodHandle hides
the target for a call, just like an interface, but more importantly the
bytecode verifier will allow any signature to be used for invokeGeneric.
I.e. (using the JSR292 pseudo java-syntax instead of pushing byte code)
you can have:
MethodHandle mh = (.... grab a method handle somewhere...)
int xx = mh.<int>invokeGeneric(42,"Hello");
Object oo = mh.<Object>invokeGeneric("Hi", "Hi");
There would be no objection to the above code by the bytecode verifier.
If the methodhandle actually holds on to the method:
int asillymethod(Object o, String s) {
return 17;
}
then the code will actually execute with no runtime exceptions. xx will
contain 17 and oo will contain a new Integer(17).
The JVM (not the bytecode) will cast each argument to the target
argument type. It will box primitives if necessary and it will
cast/unbox if the target requires a primitive and is fed a reference.
The same is applied to the return value. Obviously this will sometimes
cause object allocations to occur as a side effect of the call. However
this will not happen as often as you think. Especially when hot code is
inlined and optimized, then the casting and boxing can be completely
removed. (As I have shown here blogs.oracle.com/ohrstrom).
invokeGeneric was not introduced on a whim, it was introduced to allow
the JVM implementor to implement the generic transformations (currying
of arguments, permuting arguments et al) in static bytecode (NO bytecode
generation needed at runtime!) and not hidden inside a bunch of magic
jni calls nor any bytecode spewing library. I do not believe that the
generic transforms (generalized lambdas) can be implemented using any of
the current closure proposals.
Thus MethodHandle.invokeGeneric is an runtime checked function object.
It supports contravariant arguments since the cast will only allow
those. It supports covariant return values, again since this is what the
cast of the return value will allow. It supports int->Integer
Integer->int and similar boxing but not int->Long nor long->Integer.
(For various reasons JSR292 also has invokeExact that will fail unless
the types match exactly, no variance allowed at all, you have to cast a
string to object, (Object)"Hello", for it to be accepted as an Object
argument.)
The MethodHandle can be bound to an object instance within which the
method will execute, but it is not by itself a closure or a lambda in
the future Java sense, and it surely has no function type available for
javac compile time checking. But this does not mean that it cannot be
the building block for closures on the inside instead of using interfaces.
//Fredrik
More information about the closures-dev
mailing list