Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8300924

Method::invoke throws wrong exception type when passing wrong number of arguments to method with 4 or more parameters

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 21
    • 18.0.1, 18.0.2.1, 19.0.1, 19.0.2
    • core-libs
    • Microsoft Windows [Version 10.0.22621.1105]

    • 18
    • b08
    • generic
    • generic
    • Verified

      Here's a simple reproducer:


      import java.lang.reflect.Method;
      import java.util.stream.IntStream;

      public class Reflection {

          public static void m1(Object a) {}
          public static void m2(Object a, Object b) {}
          public static void m3(Object a, Object b, Object c) {}
          public static void m4(Object a, Object b, Object c, Object d) {}

          public static void main(String[] args) throws Exception {
              for (int i = 1; i < 5; i++) {
                  try {
                      Method m = Reflection.class.getMethod("m" + i, IntStream.range(0, i).mapToObj(x -> Object.class).toArray(Class<?>[]::new));
                      System.out.println(m);
                      m.invoke(Reflection.class);
                  }
                  catch (Exception e) {
                      e.printStackTrace();
                  }
              }
          }
      }



      On JDK 17, when running this:
      "c:\Program Files\Java\jdk-17\bin\java.exe" Reflection.java


      The above program prints the expected output


      public static void Reflection.m1(java.lang.Object)
      java.lang.IllegalArgumentException: wrong number of arguments
              at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
              at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
              at java.base/java.lang.reflect.Method.invoke(Method.java:568)
              at Reflection.main(Reflection.java:16)
              at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
              at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
              at java.base/java.lang.reflect.Method.invoke(Method.java:568)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.execute(Main.java:419)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.run(Main.java:192)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.main(Main.java:132)
      public static void Reflection.m2(java.lang.Object,java.lang.Object)
      java.lang.IllegalArgumentException: wrong number of arguments
              at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
              at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
              at java.base/java.lang.reflect.Method.invoke(Method.java:568)
              at Reflection.main(Reflection.java:16)
              at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
              at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
              at java.base/java.lang.reflect.Method.invoke(Method.java:568)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.execute(Main.java:419)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.run(Main.java:192)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.main(Main.java:132)
      public static void Reflection.m3(java.lang.Object,java.lang.Object,java.lang.Object)
      java.lang.IllegalArgumentException: wrong number of arguments
              at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
              at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
              at java.base/java.lang.reflect.Method.invoke(Method.java:568)
              at Reflection.main(Reflection.java:16)
              at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
              at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
              at java.base/java.lang.reflect.Method.invoke(Method.java:568)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.execute(Main.java:419)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.run(Main.java:192)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.main(Main.java:132)
      public static void Reflection.m4(java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object)
      java.lang.IllegalArgumentException: wrong number of arguments
              at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
              at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
              at java.base/java.lang.reflect.Method.invoke(Method.java:568)
              at Reflection.main(Reflection.java:16)
              at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
              at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
              at java.base/java.lang.reflect.Method.invoke(Method.java:568)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.execute(Main.java:419)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.run(Main.java:192)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.main(Main.java:132)



      But starting with JDK 18:
      "c:\Program Files\Java\jdk-18\bin\java.exe" Reflection.java



      The program prints:



      public static void Reflection.m1(java.lang.Object)
      java.lang.IllegalArgumentException: wrong number of arguments: 0 expected: 1
              at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.checkArgumentCount(DirectMethodHandleAccessor.java:337)
              at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:102)
              at java.base/java.lang.reflect.Method.invoke(Method.java:577)
              at Reflection.main(Reflection.java:16)
              at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
              at java.base/java.lang.reflect.Method.invoke(Method.java:577)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.execute(Main.java:421)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.run(Main.java:192)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.main(Main.java:132)
      public static void Reflection.m2(java.lang.Object,java.lang.Object)
      java.lang.IllegalArgumentException: wrong number of arguments: 0 expected: 2
              at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.checkArgumentCount(DirectMethodHandleAccessor.java:337)
              at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:102)
              at java.base/java.lang.reflect.Method.invoke(Method.java:577)
              at Reflection.main(Reflection.java:16)
              at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
              at java.base/java.lang.reflect.Method.invoke(Method.java:577)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.execute(Main.java:421)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.run(Main.java:192)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.main(Main.java:132)
      public static void Reflection.m3(java.lang.Object,java.lang.Object,java.lang.Object)
      java.lang.IllegalArgumentException: wrong number of arguments: 0 expected: 3
              at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.checkArgumentCount(DirectMethodHandleAccessor.java:337)
              at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:102)
              at java.base/java.lang.reflect.Method.invoke(Method.java:577)
              at Reflection.main(Reflection.java:16)
              at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
              at java.base/java.lang.reflect.Method.invoke(Method.java:577)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.execute(Main.java:421)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.run(Main.java:192)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.main(Main.java:132)
      public static void Reflection.m4(java.lang.Object,java.lang.Object,java.lang.Object,java.lang.Object)
      java.lang.reflect.InvocationTargetException
              at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:119)
              at java.base/java.lang.reflect.Method.invoke(Method.java:577)
              at Reflection.main(Reflection.java:16)
              at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
              at java.base/java.lang.reflect.Method.invoke(Method.java:577)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.execute(Main.java:421)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.run(Main.java:192)
              at jdk.compiler/com.sun.tools.javac.launcher.Main.main(Main.java:132)
      Caused by: java.lang.IllegalArgumentException: array is not of length 4
              at java.base/java.lang.invoke.MethodHandleStatics.newIllegalArgumentException(MethodHandleStatics.java:169)
              at java.base/java.lang.invoke.MethodHandleImpl.checkSpreadArgument(MethodHandleImpl.java:588)
              at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
              ... 7 more



      Notice how the last invocation's IllegalArgumentException is wrapped in an InvocationTargetException. There's no good reason for this to happen. There's no invocation target involved, the exception is caused by the reflection itself.

      The DirectMethodHandleAccessor::invokeImpl method hints at the size of the parameter list being relevant here (sources from JDK 19):


          @Hidden
          @ForceInline
          private Object invokeImpl(Object obj, Object[] args) throws Throwable {
              return switch (paramCount) {
                  case 0 -> target.invokeExact(obj);
                  case 1 -> target.invokeExact(obj, args[0]);
                  case 2 -> target.invokeExact(obj, args[0], args[1]);
                  case 3 -> target.invokeExact(obj, args[0], args[1], args[2]);
                  default -> target.invokeExact(obj, args);
              };
          }


      I.e. only the default case with 4+ arguments seems to be affected by the problem

            mchung Mandy Chung (Inactive)
            leder Lukas Eder
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved: