Java – reflections illegalargumentexception reason
Update – make the problem clearer
ClassCastException exception may be caused when calling a method through reflection?
When trying to call a method through reflection, I use the following stack trace as part of my application
java.lang.IllegalArgumentException: java.lang.ClassCastException@21fea1fv
at sun.reflect.GeneratedMethodAccessor332.invoke(UnkNown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.....
(remaining is my method stack trace)
I tried a sample class and passed various parameters of different types, but I always got this exception
java.lang.IllegalArgumentException: argument type mismatch at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597)
Update – this is the sample code I wrote trying to recreate the exception
Interface to create a proxy class
package my.tests;
public interface ReflectionsInterface {
public abstract void doSomething();
}
This is a test class
package my.tests;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Reflections implements ReflectionsInterface {
public static void main(String[] args) {
Reflections reflections = new Reflections();
ReflectionsInterface reflectionsProxy = reflections.createProxy(ReflectionsInterface.class);
invokeMethod(reflectionsProxy,"doSomething",null);
}
public <T> T createProxy(Class<T> entityInterface) {
EntityInvocationHandler eih = new EntityInvocationHandler(this);
T cast = entityInterface.cast(Proxy.newProxyInstance(
entityInterface.getClassLoader(),new Class[]{entityInterface},eih));
return cast;
}
public static void invokeMethod(Object obj,String methodName,Object... args) {
Method[] methods = obj.getClass().getmethods();
try {
for (Method method : methods) {
if (method.getName().equals(methodName)) {
method.invoke(obj,args);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void doSomething() {
System.out.println("woo");
}
private final static class EntityInvocationHandler implements InvocationHandler,ReflectionsInterface {
private Reflections reflectionObj;
public EntityInvocationHandler(Reflections reflectionObj) {
super();
this.reflectionObj = reflectionObj;
}
@Override
public void doSomething() {
reflectionObj.doSomething();
}
@Override
public Object invoke(Object proxy,Method method,Object[] args) throws Throwable {
Object invoke = method.invoke(this,args);
return invoke;
}
}
}
I can't understand when I will get a parameter type mismatch and cause ClassCastException I can't recreate the exception and wonder why In this case, it would be nice to recreate any of its working code or source code references that reference this exception
I went through method Class JavaDocs and source code, I can't figure out why this error occurs
Solution
I recreated the ClassCastException by modifying the example code: calling invokeMethod 10000 times with the correct parameters, and then calling the wrong one.
Main methods in the reflections class
public static void main(String[] args) {
Reflections reflections = new Reflections();
ReflectionsInterface reflectionsProxy = reflections
.createProxy(ReflectionsInterface.class);
for (int i = 0; i < 10000; i++)
invokeMethod(reflectionsProxy,ReflectionsInterface.class,"doSomething");
invokeMethod(new Object(),"doSomething");
}
Invokemethod method in the reflections class
public static void invokeMethod(Object obj,Class<?> clazz,Object... args) {
Method[] methods = clazz.getmethods();
try {
for (Method method : methods) {
if (method.getName().equals(methodName)) {
method.invoke(obj,args);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
Stack trace:
java.lang.IllegalArgumentException: java.lang.ClassCastException@603a3e21
at sun.reflect.GeneratedMethodAccessor1.invoke(UnkNown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.twbbs.pccprogram.Reflections.invokeMethod(Reflections.java:33)
at org.twbbs.pccprogram.Reflections.main(Reflections.java:16)
My explanation of ClassCastException:
When you first call invokemethod, the JVM uses a slower route, which makes debugging easier for programmers (so it's slower!), Therefore, when an incorrect parameter is passed, it will display a more friendly parameter type mismatch message
When you call invokemethod many times (16 times in my test), the JVM generates a generated methodaccessor * * * at runtime, which is faster and less error checking So when you pass a bad parameter, it will display such an ugly Java lang. ClassCastException@603a3e21 News
