类加载器之间的反射参数类型不匹配

axe*_*rod 5 java reflection classloader

对于向后兼容性测试,我正在创建我自己的类加载器来加载我以前版本的一些代码。在我拥有自定义对象(来自较旧的自定义类)之后,我将使用反射调用它的 API。但是,当此类 API 方法具有自定义参数(不是 java 库的一部分)时,例如:

public void MyMethod(MyObj a) {}
Run Code Online (Sandbox Code Playgroud)

当我使用反射调用此方法时,我得到:

java.lang.IllegalArgumentException:参数类型不匹配

因为我从默认类加载器传递 MyObj 而该方法期望从自定义类加载器获取 MyObj。

我用来调用该方法的代码(而代理是由我的自定义类加载器加载的,代理的 api 方法的参数来自我的测试类,该类由默认类加载器加载)

        private Object invoke(Object... args) {
            try {
                final String methodName = getMethodName();
                final Class<?>[] methodArgs = getMethodArgs(methodName);
                return agent.getClass().getMethod(methodName, methodArgs).invoke(agent, args);

            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
            return null;
        }

        private Class<?>[] getMethodArgs(String methodName) {
            final Method[] declaredMethods = agent.getClass().getDeclaredMethods();
            for (Method method : declaredMethods) {
                if (method.getName().equals(methodName)) {
                    return method.getParameterTypes();
                }
            }
            return new Class<?>[0];
        }

        private String getMethodName() {
            StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
            StackTraceElement e = stacktrace[3];
            return e.getMethodName();
        }
Run Code Online (Sandbox Code Playgroud)

我该如何解决这个问题?(我无法将通用接口传递给该方法,因为 myCustomObject 没有实现共享模块中存在的接口,我现在无法添加一个,因为旧的 jars 不会知道它)

小智 2

您可以使用自定义类加载器来加载扩展 MyObj 的类“DefaultCtorMyObjWrapper”(由自定义类加载器加载)。DefaultCtorMyObjWrapper 包装由默认构造函数加载的“MyObj”实例(引用应保留为对象)。DefaultCtorMyObjWrapper 重写 MyObj 的所有方法,并使用反射将调用委托给包装的 MyObj。

应该看起来像这样:

class DefaultCtorMyObjWrapper{

    Object _defaultCtorMyObj;

    public DefaultCtorMyObjWrapper(Object defaultCtorMyObj){
        _defaultCtorMyObj = defaultCtorMyObj;
    }   

    public method1(){
        // invoke method1 on _defaultCtorMyObj using reflcetion
    }

}
Run Code Online (Sandbox Code Playgroud)

如果 MyObj 的方法接收对象作为参数,您可能需要进行更多调整。