changeset 7343:fcc9fe7c628b

8001109: arity mismatch on a call to spreader method handle should elicit IllegalArgumentException Reviewed-by: twisti
author kizune
date Wed, 09 Apr 2014 13:06:37 +0400
parents e74bc78d7d50
children 8dfe74c7d7bc
files src/share/classes/java/lang/invoke/MethodHandle.java src/share/classes/java/lang/invoke/MethodHandleImpl.java src/share/classes/java/lang/invoke/MethodHandles.java test/java/lang/invoke/JavaDocExamplesTest.java
diffstat 4 files changed, 20 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/lang/invoke/MethodHandle.java	Wed Apr 09 13:16:33 2014 +0400
+++ b/src/share/classes/java/lang/invoke/MethodHandle.java	Wed Apr 09 13:06:37 2014 +0400
@@ -753,6 +753,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>
 MethodHandle equals = publicLookup()
@@ -763,6 +767,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/src/share/classes/java/lang/invoke/MethodHandleImpl.java	Wed Apr 09 13:16:33 2014 +0400
+++ b/src/share/classes/java/lang/invoke/MethodHandleImpl.java	Wed Apr 09 13:06:37 2014 +0400
@@ -454,14 +454,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;
@@ -470,9 +464,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);
     }
 
     private static final NamedFunction NF_checkSpreadArgument;
--- a/src/share/classes/java/lang/invoke/MethodHandles.java	Wed Apr 09 13:16:33 2014 +0400
+++ b/src/share/classes/java/lang/invoke/MethodHandles.java	Wed Apr 09 13:06:37 2014 +0400
@@ -1516,6 +1516,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/test/java/lang/invoke/JavaDocExamplesTest.java	Wed Apr 09 13:16:33 2014 +0400
+++ b/test/java/lang/invoke/JavaDocExamplesTest.java	Wed Apr 09 13:06:37 2014 +0400
@@ -366,6 +366,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" }));