Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用反射在外部jar中调用方法_Java_Reflection_Jar_Classloader - Fatal编程技术网

Java 如何使用反射在外部jar中调用方法

Java 如何使用反射在外部jar中调用方法,java,reflection,jar,classloader,Java,Reflection,Jar,Classloader,我想通过使用反射调用外部.jar中的方法 这是jar中的一个示例代码 public class HelloFunction implements Runnable, RequestHandler<Request> { @Override public void handle(final Request request) { System.out.println("handle : " + request); } @Override

我想通过使用反射调用外部.jar中的方法

这是jar中的一个示例代码

public class HelloFunction implements Runnable, RequestHandler<Request> {

    @Override
    public void handle(final Request request) {
        System.out.println("handle : " + request);
    }

    @Override
    public void run() {
        System.out.println("run......");
    }
}
然后我将这个jar加载到一个单独的java程序中,并尝试调用HelloFunction.handle方法。这是该部件的示例代码

public class App {

    public static void main(String[] args) {
        test();
    }

    public static void test(){

        try{

            final Class<?> functionClass = getClassFromFunctionJar("com.hello.HelloFunction");

            final Object functionClassObject = functionClass.newInstance();

            if(functionClassObject instanceof RequestHandler){

                @SuppressWarnings("unchecked")
                final RequestHandler<Object> handler = RequestHandler.class.cast(functionClassObject);

                final Object inputObject = getRequestClass(functionClass).newInstance();

                handler.handle(inputObject);


            }

        }catch(final Exception e){

            System.err.println(e.getMessage());

        }
    }

    public static Class<?> getRequestClass(final Class<?> cls) throws FunctionInvokerException{

        try{
            final Type[] types = cls.getGenericInterfaces();

            for(Type type : types){

                //check RequestHandler
                if(type.getTypeName().contains(RequestHandler.class.getName())){

                    final ParameterizedType parameterizedType = (ParameterizedType) type;

                    // [0]=> Request Type
                    final String inputClassName = parameterizedType.getActualTypeArguments()[0].getTypeName();
                    return getClassFromFunctionJar(inputClassName);

                }

            }

            throw new Exception("UNABLE_TO_FIND_REQUEST_TYPE");

        }catch(final Exception e){
            throw new FunctionInvokerException(e);
        }

    }

    private static Class<?> getClassFromFunctionJar(final String className) throws ClassNotFoundException, MalformedURLException{
        final ClassLoader classLoader = URLClassLoader.newInstance(new URL[]{new URL("file:" + "/jar-location/hello.jar")}, App.class.getClassLoader());
        return Class.forName(className, true, classLoader);
    }

}
您可以在这里看到,我使用getClassFromFunctionJar方法从jar加载类。getRequestClass方法用于查找HelloFunction.handle方法输入参数的类类型。 在调用handle方法之前,一切都正常


最后我得到一个错误,说com.hello.Request不能转换为com.hello.Request。您能帮我解决这个问题吗。

不同类加载器加载的相同类定义被JVM视为两个不同的类

您的代码URLClassLoader.newInstance,同时获取不同的类加载器

firsthandlerparameter是:URLClassLoader1&com.hello.Request

第二个InputObject是:URLClassLoader2&com.hello.Request

无法将com.hello.Request转换为com.hello.Request

实际误差为

URLClassLoader2 com.hello.Request无法强制转换为URLClassLoader1 com.hello.Request

并建议:

private static final ClassLoader classLoader = URLClassLoader.newInstance(new URL[]{new URL("file:" + "/jar-location/hello.jar")}, App.class.getClassLoader());

private static Class<?> getClassFromFunctionJar(final String className) throws ClassNotFoundException, MalformedURLException{
    return Class.forName(className, true, classLoader);
}

为什么需要反射?com.hello.Request不能转换为com.hello.Request始终意味着您已经通过两个不同的类加载器加载了两次类。由于硬编码引用,已经静态加载了类,并且在加载实现时加载了第二个副本。这不是作为答案发布的,因为虽然我可以告诉您为什么会出现错误,但没有足够的信息告诉您如何修复错误,而且我的类加载器专业知识有些过时。是的。问题是我加载了两个类加载器,现在修复了它。谢谢。非常感谢你的回答。现在修好了。