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

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>