maybe someone can explain to me why method handles behave this way in my
case.
Bascially I have a handle for Class#getDeclaredConstructor(Class...) I
created via unreflect.
this handle is then created as a AdapterMethodHandle$AsVargsCollector.
My targetType is Object(Object,Object) and the arguments to the call are
the Class, and an empty Class[]. So the next steps are asType with the
target type, adding a guard with catch, then my guards for the arguments
and last I do an invokeWithArguments.
What I get now is a ClassCastException with the message required class
java.lang.Class but encountered class [Ljava.lang.Class;
The guards are unrelated to the problem, since it happens without them
as well.
Now can anyone explain me why I get that exception? It doesn't really
make sense to me atm.
bye Jochen
--
Jochen "blackdrag" Theodorou - Groovy Project Tech Lead
blog: http://blackdragsview.blogspot.com/
german groovy discussion newsgroup: de.comp.lang.misc
For Groovy programming sources visit http://groovy-lang.org
can someone tell me the mistake?
bye Jochen
or in other words: I should not use invokeWithArguments for this.
If I wanted to use the same target type... since that is what my call
site gives me... and I wanted to use invokeExact instead, how would I
have to change the program?
bye blackdrag
java.lang.invoke.WrongMethodTypeException:
(Ljava/lang/Object;[Ljava/lang/Object;)V cannot be called without a
receiver argument as ([Ljava/lang/Object;)Ljava/lang/Object;
imho casting to Object and Object[] in
mh.invokeExact((Object)Class.class, (Object[])new Class[0]);
is without effect, since invokeExact is a vargs method an everything
will just be put into an Object[] anyway. We had not a compiler change
for this kind of thing, had we?
bye Jochen
Am 07.02.2012 17:52, schrieb Jim Laskey:
> Try
>
> MethodType type = MethodType.methodType(Constructor.class, Class[].class);
> MethodHandle mh = MethodHandles.lookup().findVirtual(Class.class, "getDeclaredConstructor", type);
> MethodType target = MethodType.methodType(void.class, Object.class, Object[].class);
> mh = MethodHandles.explicitCastArguments(mh, target);
> mh.invokeExact((Object)Class.class, (Object[])new Class[0]);
>
> Cheers,
>
> -- Jim
later than jdk7u2? oh boy. I would feel better if I could find a bug
report that shows the problem and that is resolved. Then I would at
least have something for the release notes. But I didn't find anything
that looks fitting. The only one that seems to be slightly fitting was
fixed a year ago and surely that fix is part of jdk7u2 already.
You said for
> MethodType type = MethodType.methodType(Constructor.class, Class[].class);
> MethodHandle mh = MethodHandles.lookup().findVirtual(Class.class, "getDeclaredConstructor", type);
> MethodType target = MethodType.methodType(Object.class, Object.class, Object.class);
> mh = mh.asType(target);
> mh.invokeWithArguments(Class.class,new Class[0]);
I probably have to wrap something... can you explain what you mean?
bye Jochen
Jochen,
I believe you have found a bug in Eclipse (I suppose you use Eclipse).
mh.invoke() is compiled as (Object)mh.invoke() by Eclipse instead of
(void)mh.invoke(),
hence that's why it works for Jim and not for you.
Now, how varargs works.
when you create a method handle with lookup.find* or lookup.unreflect()
on a method
which is a varargs (comp�led with the ACC_VARARGS bit) then
the created method handle has its varargs collector bit set.
A way to test if the varargs collector bit is set or not is to call,
methodHandle.isVarargCollector().
A method handle with the a varargs collector bit set is able to group
arguments in an array
only if invoked with invoke() or invokeWithArguments() but not with
invokeExact which
never do any boxing or varargs magics.
Also, when asType() is called on a method handle, the varargs collector
bit set is lost,
so if you still want a varargs call you need to call
asVarargsCollector() to set the bit.
As a meta-note, invoking a method handle with invoke or invokeArguments and
the varargs collector bit set is slow. It's only intended to be use when
you want to call a lambda/closure that is defined as a varargs.
Otherwise you should use asCollector which is way faster (at least
currently with Hotspot).
cheers,
R�mi
No actually your long explanation gave me the idea of what is wrong
> Now, how varargs works.
> when you create a method handle with lookup.find* or lookup.unreflect()
> on a method
> which is a varargs (comp�led with the ACC_VARARGS bit) then
> the created method handle has its varargs collector bit set.
> A way to test if the varargs collector bit is set or not is to call,
> methodHandle.isVarargCollector().
>
> A method handle with the a varargs collector bit set is able to group
> arguments in an array
> only if invoked with invoke() or invokeWithArguments() but not with
> invokeExact which
> never do any boxing or varargs magics.
ok, explicitCastArguments will do probably needed casting and boxing for
me, and since Groovy does the vargs logic on its own, there seems to be
no reason to still use invokeWithArguments anymore. I only failed to
understand invokeExact till now.
What I stupidly failed to see is that invokeExact itself realizes a call
site and thus has a different target type.
so what I do now is
> MethodHandle call = handle.asSpreader(Object[].class, args.length);
> call = call.asType(MethodType.methodType(Object.class,Object[].class));
and then I can do my
call.invokeExact(args)
without problem it seems.