Jim's example works on 7u2 for me as well. The cast is not without effect at all. It is crucial to have it!
That is because of the so called "Signature polymorphism" of the 'invokeExact()' and plain 'invoke()' methods (read the API documentation for more details: http://docs.oracle.com/javase/7/docs/api/index.html?java/lang/invoke/MethodHandles.html). In short, 'invokeExact()' and 'invoke()' are declared as vararg methods as you correctly noticed. But that's just to make them compile and "operate with any of a wide range of call signatures and return types". However at runtime the method is called with the "symbolic type descriptor derived from the actual argument and return types, not from the method declaration". And in the case of "invokeExect()" the exact symbolic type descriptor has to match the signature of the calle, otherwise you'll get a WrongMethodType exception. I've slightly extended Jim's example to exactly match your desired target type: ========================================================== import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.reflect.Constructor; public class Varargs { public static void main(String[] args) { try { 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 = MethodHandles.explicitCastArguments(mh, target); Object constructor = mh.invokeExact((Object)Class.class, (Object)null); System.out.println(constructor); MethodType target1 = MethodType.methodType(Object.class, Object.class, Object[].class); mh = MethodHandles.explicitCastArguments(mh, target1); constructor = mh.invokeExact((Object)Class.class, (Object[])new Class[0]); System.out.println(constructor); } catch(Throwable e) { System.out.println(e); } } } ========================================================== As mentioned before, it runs just fine with jdk7u2: ========================================================== java -showversion -cp ~/Java/invokedynamic/ Varargs java version "1.7.0_02" Java(TM) SE Runtime Environment (build 1.7.0_02-b13) Java HotSpot(TM) 64-Bit Server VM (build 22.0-b10, mixed mode) private java.lang.Class() private java.lang.Class() ========================================================== One general advice is to use the -XX:+TraceMethodHandles paramter to trace the VM is handling MethodHandles. Unfortunately, this parameter is only available in debug builds, but fortunately it's not too hard to compile a debug version of the VM yourself. Yyou can than just replace the original libjvm.so in the JDK directory with the one build by you. I would also recommend to use a new Hotspot version from http://hg.openjdk.java.net/hsx/hotspot-main/hotspot for this purpose which already has the change "7120468: SPARC/x86: use frame::describe to enhance trace_method_handle". This makes the additional information which you get with -XX:+TraceMethodHandles and -XX:+Verbose -XX:+WizardMode a lot more readable. Here's how that output looks for the following code snippet: MethodType target = MethodType.methodType(Object.class, Object.class, Object.class); mh = MethodHandles.explicitCastArguments(mh, target); Object constructor = mh.invokeExact((Object)Class.class, (Object)null); System.out.println(constructor); I've shoretend it nevertheless, because it is really verbose. Nevertheless you can see how the adapter chain is walked which casts the arguments to the required types and finally calls the actual target of the method handle: MH invokeExact MethodHandle:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; : #( java.lang.Object a1, java.lang.Object a2 ) => { --- next target: java.lang.invoke.AdapterMethodHandle mark(hash 0,age 0) - klass: 'java/lang/invoke/AdapterMethodHandle' - ---- fields (total size 6 words): - private 'vmentry' 'B' @12 0 - 'vmtarget' 'Ljava/lang/Object;' @24 a 'java/lang/invoke/AdapterMethodHandle' (ecdcaa40 ecdb1108) - private 'type' 'Ljava/lang/invoke/MethodType;' @28 a 'java/lang/invoke/MethodType' = (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; (ecdb1108 0) - private final 'vmargslot' 'I' @32 0 - private final 'argument' 'Ljava/lang/Object;' @36 a 'java/lang/Class' = 'java/lang/Class'[] (ecd63828 cc200) - private final 'conversion' 'I' @40 836096 (cc200) convert object v3 = checkcast(a2, [Ljava.lang.Class;); --- next target: java.lang.invoke.AdapterMethodHandle mark(hash 0,age 0) - klass: 'java/lang/invoke/AdapterMethodHandle' - ---- fields (total size 6 words): - private 'vmentry' 'B' @12 0 - 'vmtarget' 'Ljava/lang/Object;' @24 a 'java/lang/invoke/AdapterMethodHandle$AsVarargsCollector' (ecdb1420 ecdca9c8) - private 'type' 'Ljava/lang/invoke/MethodType;' @28 a 'java/lang/invoke/MethodType' = (Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/reflect/Constructor; (ecdca9c8 1) - private final 'vmargslot' 'I' @32 1 - private final 'argument' 'Ljava/lang/Object;' @36 a 'java/lang/Class' = 'java/lang/Class' (ecd60b70 cc200) - private final 'conversion' 'I' @40 836096 (cc200) convert object v4 = checkcast(a1, java.lang.Class); --- next target: java.lang.invoke.AdapterMethodHandle$AsVarargsCollector mark(hash 0,age 0) - klass: 'java/lang/invoke/AdapterMethodHandle$AsVarargsCollector' - ---- fields (total size 7 words): - private 'vmentry' 'B' @12 0 - 'vmtarget' 'Ljava/lang/Object;' @24 a 'java/lang/invoke/DirectMethodHandle' (ecdb1388 ecdb10d0) - private 'type' 'Ljava/lang/invoke/MethodType;' @28 a 'java/lang/invoke/MethodType' = (Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/reflect/Constructor; (ecdb10d0 2) - private final 'vmargslot' 'I' @32 2 - private final 'argument' 'Ljava/lang/Object;' @36 NULL (0 0) - private final 'conversion' 'I' @40 0 - final 'target' 'Ljava/lang/invoke/MethodHandle;' @44 a 'java/lang/invoke/DirectMethodHandle' (ecdb1388 ecd63828) - final 'arrayType' 'Ljava/lang/Class;' @48 a 'java/lang/Class' = 'java/lang/Class'[] (ecd63828 ecdca930) - 'cache' 'Ljava/lang/invoke/MethodHandle;' @52 a 'java/lang/invoke/AdapterMethodHandle' (ecdca930 1) --- next target: java.lang.invoke.DirectMethodHandle mark(hash 0,age 0) - klass: 'java/lang/invoke/DirectMethodHandle' - ---- fields (total size 5 words): - private 'vmentry' 'B' @12 0 - 'vmtarget' 'Ljava/lang/Object;' @24 {method} 'getDeclaredConstructor' '([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;' in 'java/lang/Class'[2,2] (c16124f0 ecdb10d0) - private 'type' 'Ljava/lang/invoke/MethodType;' @28 a 'java/lang/invoke/MethodType' = (Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/reflect/Constructor; (ecdb10d0 fffffffe) - private final 'vmindex' 'I' @32 -2 (fffffffe) return invokespecial getDeclaredConstructor([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;(v4, v3) } MH adapter_check_cast MethodHandle:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; : #( java.lang.Object a1, java.lang.Object a2 ) => { --- next target: java.lang.invoke.AdapterMethodHandle mark(hash 0,age 0) - klass: 'java/lang/invoke/AdapterMethodHandle' - ---- fields (total size 6 words): - private 'vmentry' 'B' @12 0 - 'vmtarget' 'Ljava/lang/Object;' @24 a 'java/lang/invoke/AdapterMethodHandle' (ecdcaa40 ecdb1108) - private 'type' 'Ljava/lang/invoke/MethodType;' @28 a 'java/lang/invoke/MethodType' = (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; (ecdb1108 0) - private final 'vmargslot' 'I' @32 0 - private final 'argument' 'Ljava/lang/Object;' @36 a 'java/lang/Class' = 'java/lang/Class'[] (ecd63828 cc200) - private final 'conversion' 'I' @40 836096 (cc200) convert object v3 = checkcast(a2, [Ljava.lang.Class;); --- next target: java.lang.invoke.AdapterMethodHandle mark(hash 0,age 0) - klass: 'java/lang/invoke/AdapterMethodHandle' - ---- fields (total size 6 words): - private 'vmentry' 'B' @12 0 - 'vmtarget' 'Ljava/lang/Object;' @24 a 'java/lang/invoke/AdapterMethodHandle$AsVarargsCollector' (ecdb1420 ecdca9c8) - private 'type' 'Ljava/lang/invoke/MethodType;' @28 a 'java/lang/invoke/MethodType' = (Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/reflect/Constructor; (ecdca9c8 1) - private final 'vmargslot' 'I' @32 1 - private final 'argument' 'Ljava/lang/Object;' @36 a 'java/lang/Class' = 'java/lang/Class' (ecd60b70 cc200) - private final 'conversion' 'I' @40 836096 (cc200) convert object v4 = checkcast(a1, java.lang.Class); --- next target: java.lang.invoke.AdapterMethodHandle$AsVarargsCollector mark(hash 0,age 0) - klass: 'java/lang/invoke/AdapterMethodHandle$AsVarargsCollector' - ---- fields (total size 7 words): - private 'vmentry' 'B' @12 0 - 'vmtarget' 'Ljava/lang/Object;' @24 a 'java/lang/invoke/DirectMethodHandle' (ecdb1388 ecdb10d0) - private 'type' 'Ljava/lang/invoke/MethodType;' @28 a 'java/lang/invoke/MethodType' = (Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/reflect/Constructor; (ecdb10d0 2) - private final 'vmargslot' 'I' @32 2 - private final 'argument' 'Ljava/lang/Object;' @36 NULL (0 0) - private final 'conversion' 'I' @40 0 - final 'target' 'Ljava/lang/invoke/MethodHandle;' @44 a 'java/lang/invoke/DirectMethodHandle' (ecdb1388 ecd63828) - final 'arrayType' 'Ljava/lang/Class;' @48 a 'java/lang/Class' = 'java/lang/Class'[] (ecd63828 ecdca930) - 'cache' 'Ljava/lang/invoke/MethodHandle;' @52 a 'java/lang/invoke/AdapterMethodHandle' (ecdca930 1) --- next target: java.lang.invoke.DirectMethodHandle mark(hash 0,age 0) - klass: 'java/lang/invoke/DirectMethodHandle' - ---- fields (total size 5 words): - private 'vmentry' 'B' @12 0 - 'vmtarget' 'Ljava/lang/Object;' @24 {method} 'getDeclaredConstructor' '([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;' in 'java/lang/Class'[2,2] (c16124f0 ecdb10d0) - private 'type' 'Ljava/lang/invoke/MethodType;' @28 a 'java/lang/invoke/MethodType' = (Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/reflect/Constructor; (ecdb10d0 fffffffe) - private final 'vmindex' 'I' @32 -2 (fffffffe) return invokespecial getDeclaredConstructor([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;(v4, v3) } MH adapter_check_cast MethodHandle:(Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/reflect/Constructor; : #( java.lang.Object a1, [Ljava.lang.Class; a2 ) => { --- next target: java.lang.invoke.AdapterMethodHandle mark(hash 0,age 0) - klass: 'java/lang/invoke/AdapterMethodHandle' - ---- fields (total size 6 words): - private 'vmentry' 'B' @12 0 - 'vmtarget' 'Ljava/lang/Object;' @24 a 'java/lang/invoke/AdapterMethodHandle$AsVarargsCollector' (ecdb1420 ecdca9c8) - private 'type' 'Ljava/lang/invoke/MethodType;' @28 a 'java/lang/invoke/MethodType' = (Ljava/lang/Object;[Ljava/lang/Class;)Ljava/lang/reflect/Constructor; (ecdca9c8 1) - private final 'vmargslot' 'I' @32 1 - private final 'argument' 'Ljava/lang/Object;' @36 a 'java/lang/Class' = 'java/lang/Class' (ecd60b70 cc200) - private final 'conversion' 'I' @40 836096 (cc200) convert object v3 = checkcast(a1, java.lang.Class); --- next target: java.lang.invoke.AdapterMethodHandle$AsVarargsCollector mark(hash 0,age 0) - klass: 'java/lang/invoke/AdapterMethodHandle$AsVarargsCollector' - ---- fields (total size 7 words): - private 'vmentry' 'B' @12 0 - 'vmtarget' 'Ljava/lang/Object;' @24 a 'java/lang/invoke/DirectMethodHandle' (ecdb1388 ecdb10d0) - private 'type' 'Ljava/lang/invoke/MethodType;' @28 a 'java/lang/invoke/MethodType' = (Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/reflect/Constructor; (ecdb10d0 2) - private final 'vmargslot' 'I' @32 2 - private final 'argument' 'Ljava/lang/Object;' @36 NULL (0 0) - private final 'conversion' 'I' @40 0 - final 'target' 'Ljava/lang/invoke/MethodHandle;' @44 a 'java/lang/invoke/DirectMethodHandle' (ecdb1388 ecd63828) - final 'arrayType' 'Ljava/lang/Class;' @48 a 'java/lang/Class' = 'java/lang/Class'[] (ecd63828 ecdca930) - 'cache' 'Ljava/lang/invoke/MethodHandle;' @52 a 'java/lang/invoke/AdapterMethodHandle' (ecdca930 1) --- next target: java.lang.invoke.DirectMethodHandle mark(hash 0,age 0) - klass: 'java/lang/invoke/DirectMethodHandle' - ---- fields (total size 5 words): - private 'vmentry' 'B' @12 0 - 'vmtarget' 'Ljava/lang/Object;' @24 {method} 'getDeclaredConstructor' '([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;' in 'java/lang/Class'[2,2] (c16124f0 ecdb10d0) - private 'type' 'Ljava/lang/invoke/MethodType;' @28 a 'java/lang/invoke/MethodType' = (Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/reflect/Constructor; (ecdb10d0 fffffffe) - private final 'vmindex' 'I' @32 -2 (fffffffe) return invokespecial getDeclaredConstructor([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;(v3, a2) } MH adapter_retype_only MethodHandle:(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/reflect/Constructor; : #( java.lang.Class a1, [Ljava.lang.Class; a2 ) => { --- next target: java.lang.invoke.AdapterMethodHandle$AsVarargsCollector mark(hash 0,age 0) - klass: 'java/lang/invoke/AdapterMethodHandle$AsVarargsCollector' - ---- fields (total size 7 words): - private 'vmentry' 'B' @12 0 - 'vmtarget' 'Ljava/lang/Object;' @24 a 'java/lang/invoke/DirectMethodHandle' (ecdb1388 ecdb10d0) - private 'type' 'Ljava/lang/invoke/MethodType;' @28 a 'java/lang/invoke/MethodType' = (Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/reflect/Constructor; (ecdb10d0 2) - private final 'vmargslot' 'I' @32 2 - private final 'argument' 'Ljava/lang/Object;' @36 NULL (0 0) - private final 'conversion' 'I' @40 0 - final 'target' 'Ljava/lang/invoke/MethodHandle;' @44 a 'java/lang/invoke/DirectMethodHandle' (ecdb1388 ecd63828) - final 'arrayType' 'Ljava/lang/Class;' @48 a 'java/lang/Class' = 'java/lang/Class'[] (ecd63828 ecdca930) - 'cache' 'Ljava/lang/invoke/MethodHandle;' @52 a 'java/lang/invoke/AdapterMethodHandle' (ecdca930 1) --- next target: java.lang.invoke.DirectMethodHandle mark(hash 0,age 0) - klass: 'java/lang/invoke/DirectMethodHandle' - ---- fields (total size 5 words): - private 'vmentry' 'B' @12 0 - 'vmtarget' 'Ljava/lang/Object;' @24 {method} 'getDeclaredConstructor' '([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;' in 'java/lang/Class'[2,2] (c16124f0 ecdb10d0) - private 'type' 'Ljava/lang/invoke/MethodType;' @28 a 'java/lang/invoke/MethodType' = (Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/reflect/Constructor; (ecdb10d0 fffffffe) - private final 'vmindex' 'I' @32 -2 (fffffffe) return invokespecial getDeclaredConstructor([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;(a1, a2) } MH invokespecial MethodHandle:(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/reflect/Constructor; : #( java.lang.Class a1, [Ljava.lang.Class; a2 ) => { --- next target: java.lang.invoke.DirectMethodHandle mark(hash 0,age 0) - klass: 'java/lang/invoke/DirectMethodHandle' - ---- fields (total size 5 words): - private 'vmentry' 'B' @12 0 - 'vmtarget' 'Ljava/lang/Object;' @24 {method} 'getDeclaredConstructor' '([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;' in 'java/lang/Class'[2,2] (c16124f0 ecdb10d0) - private 'type' 'Ljava/lang/invoke/MethodType;' @28 a 'java/lang/invoke/MethodType' = (Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/reflect/Constructor; (ecdb10d0 fffffffe) - private final 'vmindex' 'I' @32 -2 (fffffffe) return invokespecial getDeclaredConstructor([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;(a1, a2) } private java.lang.Class() On Tue, Feb 7, 2012 at 6:17 PM, Jochen Theodorou <blackd...@gmx.org> wrote: > > That will produce a > > 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 >> >> On 2012-02-07, at 12:37 PM, Jochen Theodorou wrote: >> >>> Am 07.02.2012 17:29, schrieb Jim Laskey: >>>>>>> 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]); >>>> >>>> As soon as you mh = mh.asType(target); it is no longer vararg, so it >>>> is treating new Class[0] as the second argument cast to Object. If >>>> you are trying to type as (Object , Object[]). I think you are going >>>> to run into difficulties validating (Class[]) Object[]. You may have >>>> to add a wrapper to get what you want, but you could also try using >>>> asCollector. >>> >>> 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 >>> >>> -- >>> 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 >>> >> > > > -- > 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 > > _______________________________________________ > mlvm-dev mailing list > mlvm-dev@openjdk.java.net > http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev _______________________________________________ mlvm-dev mailing list mlvm-dev@openjdk.java.net http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev