OpenJDK / portola / portola
changeset 20530:b54a1f5cd35f
8001109: arity mismatch on a call to spreader method handle should elicit IllegalArgumentException
Summary: Document error conditions that may occur when calling a "spreader" method handle. Use IAE in all cases.
Reviewed-by: twisti, vlivanov
author | jrose |
---|---|
date | Sat, 05 Oct 2013 05:30:39 -0700 |
parents | b49b07206f7d |
children | 14c2a04f21e6 |
files | jdk/src/share/classes/java/lang/invoke/MethodHandle.java jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java jdk/src/share/classes/java/lang/invoke/MethodHandles.java jdk/test/java/lang/invoke/JavaDocExamplesTest.java |
diffstat | 4 files changed, 20 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandle.java Sat Oct 05 05:30:39 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandle.java Sat Oct 05 05:30:39 2013 -0700 @@ -804,6 +804,10 @@ * to the target method handle. * (The array may also be null when zero elements are required.) * <p> + * If, when the adapter is called, the supplied array argument does + * not have the correct number of elements, the adapter will throw + * an {@link IllegalArgumentException} instead of invoking the target. + * <p> * Here are some simple examples of array-spreading method handles: * <blockquote><pre>{@code MethodHandle equals = publicLookup() @@ -814,6 +818,12 @@ MethodHandle eq2 = equals.asSpreader(Object[].class, 2); assert( (boolean) eq2.invokeExact(new Object[]{ "me", "me" })); assert(!(boolean) eq2.invokeExact(new Object[]{ "me", "thee" })); +// try to spread from anything but a 2-array: +for (int n = 0; n <= 10; n++) { + Object[] badArityArgs = (n == 2 ? null : new Object[n]); + try { assert((boolean) eq2.invokeExact(badArityArgs) && false); } + catch (IllegalArgumentException ex) { } // OK +} // spread both arguments from a String array: MethodHandle eq2s = equals.asSpreader(String[].class, 2); assert( (boolean) eq2s.invokeExact(new String[]{ "me", "me" }));
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java Sat Oct 05 05:30:39 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandleImpl.java Sat Oct 05 05:30:39 2013 -0700 @@ -460,14 +460,8 @@ } static void checkSpreadArgument(Object av, int n) { - // FIXME: regression test for bug 7141637 erroneously expects an NPE, and other tests may expect IAE - // but the actual exception raised by an arity mismatch should be WMTE - final boolean RAISE_RANDOM_EXCEPTIONS = true; // FIXME: delete in JSR 292 M1 if (av == null) { if (n == 0) return; - int len; - if (RAISE_RANDOM_EXCEPTIONS) - len = ((Object[])av).length; // throw NPE; but delete this after tests are fixed } else if (av instanceof Object[]) { int len = ((Object[])av).length; if (len == n) return; @@ -476,9 +470,7 @@ if (len == n) return; } // fall through to error: - if (RAISE_RANDOM_EXCEPTIONS) - throw newIllegalArgumentException("Array is not of length "+n); - throw new WrongMethodTypeException("Array is not of length "+n); + throw newIllegalArgumentException("array is not of length "+n); } /**
--- a/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Sat Oct 05 05:30:39 2013 -0700 +++ b/jdk/src/share/classes/java/lang/invoke/MethodHandles.java Sat Oct 05 05:30:39 2013 -0700 @@ -1511,6 +1511,9 @@ * <p> * Before invoking its target, the invoker will spread the final array, apply * reference casts as necessary, and unbox and widen primitive arguments. + * If, when the invoker is called, the supplied array argument does + * not have the correct number of elements, the invoker will throw + * an {@link IllegalArgumentException} instead of invoking the target. * <p> * This method is equivalent to the following code (though it may be more efficient): * <p><blockquote><pre>
--- a/jdk/test/java/lang/invoke/JavaDocExamplesTest.java Sat Oct 05 05:30:39 2013 -0700 +++ b/jdk/test/java/lang/invoke/JavaDocExamplesTest.java Sat Oct 05 05:30:39 2013 -0700 @@ -264,6 +264,12 @@ MethodHandle eq2 = equals.asSpreader(Object[].class, 2); assert( (boolean) eq2.invokeExact(new Object[]{ "me", "me" })); assert(!(boolean) eq2.invokeExact(new Object[]{ "me", "thee" })); +// try to spread from anything but a 2-array: +for (int n = 0; n <= 10; n++) { + Object[] badArityArgs = (n == 2 ? null : new Object[n]); + try { assert((boolean) eq2.invokeExact(badArityArgs) && false); } + catch (IllegalArgumentException ex) { } // OK +} // spread both arguments from a String array: MethodHandle eq2s = equals.asSpreader(String[].class, 2); assert( (boolean) eq2s.invokeExact(new String[]{ "me", "me" }));