-
Bug
-
Resolution: Fixed
-
P4
-
18.0.1, 18.0.2.1, 19.0.1, 19.0.2
-
Microsoft Windows [Version 10.0.22621.1105]
-
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
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