On Jun 11, 2011, at 2:18 PM, Attila Szegedi wrote:
> And BTW, attempts at using invoke() or invokeExact() didn't work either… They
> all behave strangely. What's the sanctioned way to pass an array explicitly
> as a vararg argument?
See the updated example below. The javadoc for invokeWithArguments contains
rules that imply the behavior you are seeing. In other words, earlier
implementations were broken.
If you call a varargs method with invokeExact, no transformations will be done.
This is the most direct way to turn off the varargs transformation (of
collecting arguments into an array). But this requires explicit, static typing.
Except for invokeExact, a varargs method routinely performs the varargs
transformation. By analogy with the Java language, you can only avoid the
varargs transformation if you supply an explicitly typed (statically typed)
array for the last argument. If the last argument is not an explicitly typed
array, the argument will be taken to be a single element of an implicitly
specified argument array. That's what is happening in your example.
More specifically, the convenience method invokeWithArguments works like a
plain invoke but only on Object types. It cannot express static array types
(Object[] or int[]) so it cannot bypass the varargs transformation.
There's one more thing you can do: turn off the "varargs bit" with
asFixedArity. That's probably the most direct way to avoid the varargs
transformation, in the setting of untyped (Object-only) programming.
-- John
public class TestVarArgInvoke {
public static void main(String[] args) throws Throwable {
java.lang.invoke.MethodHandle x =
java.lang.invoke.MethodHandles.publicLookup().unreflect(
TestVarArgInvoke.class.getMethod("x", int.class, int[].class));
for (int i = 0; i < 20; i++) {
try {
System.out.print("case "+i+": ");
test(x, i);
} catch (Exception ex) {
System.out.print("*** throw "+ex); ex.printStackTrace();
}
}
}
static void test(java.lang.invoke.MethodHandle x, int i) throws Throwable {
switch (i) {
case 0: x.invokeWithArguments(
new TestVarArgInvoke(), 1, new int[] { 2 });
/*
java.lang.ClassCastException: [I cannot be cast to
java.lang.Numberjava.lang.ClassCastException: [I cannot be cast to
java.lang.Number
at
sun.invoke.util.ValueConversions.primitiveConversion(ValueConversions.java:231)
at
sun.invoke.util.ValueConversions.unboxInteger(ValueConversions.java:76)
at
java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:571)
at
java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:568)
at TestVarArgInvoke.main(TestVarArgInvoke.java:7)
*/
return;
case 1: x.asFixedArity().invokeWithArguments(
new TestVarArgInvoke(), 1, new int[] { 2 }); return;
case 2: x.invokeExact(new TestVarArgInvoke(), 1, new int[] { 2 }); return;
case 3: x.invoke(new TestVarArgInvoke(), 1, new int[] { 2 }); return;
case 4: x.invoke((Object)new TestVarArgInvoke(), (Object)1, new int[] { 2
}); return;
case 5: x.invoke((Object)new TestVarArgInvoke(), (Object)1, (Object) new
int[] { 2 });
/*
java.lang.ClassCastException: [I cannot be cast to
java.lang.Numberjava.lang.ClassCastException: [I cannot be cast to
java.lang.Number
at
sun.invoke.util.ValueConversions.primitiveConversion(ValueConversions.java:231)
at
sun.invoke.util.ValueConversions.unboxInteger(ValueConversions.java:76)
at TestVarArgInvoke.test(TestVarArgInvoke.java:33)
at TestVarArgInvoke.main(TestVarArgInvoke.java:9)
*/
return;
case 6: x.invokeExact(new TestVarArgInvoke(), 1, 2);
/*
java.lang.invoke.WrongMethodTypeException: (LTestVarArgInvoke;I[I)V cannot be
called as (LTestVarArgInvoke;II)Vjava.lang.invoke.WrongMethodTypeException:
(LTestVarArgInvoke;I[I)V cannot be called as (LTestVarArgInvoke;II)V
at TestVarArgInvoke.test(TestVarArgInvoke.java:37)
at TestVarArgInvoke.main(TestVarArgInvoke.java:9)
*/
return;
}
System.out.println();
}
public void x(int a, int... b) {
System.out.println(a+java.util.Arrays.toString(b));
}
}
_______________________________________________
mlvm-dev mailing list
[email protected]
http://mail.openjdk.java.net/mailman/listinfo/mlvm-dev