我正在使用java來做一些與C++動態庫使用相同的事情。使用由Classloader創建的對象無需接口調用或反映調用?
我沒有找到直接使用相同類對象而沒有反射調用樣式代碼的方法。
這是我的動態庫代碼,我把它做成一個罐子。
package com.demo;
public class Logic {
public String doWork() {
System.out.println("Hello from Dll");
return "Dll";
}
}
在我的主應用程序,我可以創建一個URLClassLoader實例,調用由反映是好的:
public class Main {
public static void main(String[] args) throws MalformedURLException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
File file = new File("C:\\plugin.jar");
URL url = file.toURI().toURL();
URL[] urls = {url};
ClassLoader parentLoader = Thread.currentThread().getContextClassLoader();
ClassLoader loader = new URLClassLoader(urls, parentLoader);
Thread.currentThread().setContextClassLoader(loader);
Class<?> clazz = loader.loadClass("com.demo.Logic");
System.out.println("New Instance!!");
Object logic = clazz.newInstance();
Method method = logic.getClass().getMethod("doWork");
method.invoke(logic);
}
輸出:
New Instance!!
Hello from Dll
但是,當我更改代碼,而無需使用Reflect invoke:
public class Main {
public static void main(String[] args) throws MalformedURLException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
File file = new File("C:\\plugin.jar");
URL url = file.toURI().toURL();
URL[] urls = {url};
ClassLoader parentLoader = Thread.currentThread().getContextClassLoader();
ClassLoader loader = new URLClassLoader(urls, parentLoader);
Thread.currentThread().setContextClassLoader(loader);
Class<?> clazz = loader.loadClass("com.demo.Logic");
Logic logic = (Logic)clazz.newInstance();
logic.doWork();
}
}
編譯成功(與外部模塊編譯),但是當我運行程序時,它沒有在該行Logic logic = (Logic)clazz.newInstance();
例外:
Exception in thread "main" java.lang.NoClassDefFoundError: com/demo/Logic
at Main.main(Main.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.ClassNotFoundException: com.demo.Logic
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
... 6 more
有沒有什麼辦法讓它工作嗎?沒有體現/接口。(在C++中,我可以很容易地做到這一點,共享相同的結構/類中聲明,確保使用相同的編譯器編譯兩個部分。恕我直言,Java的會做同樣)
補充說明1
我想改變當前的類加載器的行爲,使其認識到動態加載的類,這是嘗試簡單和幼稚,找不到其他方向:
ClassLoader parentLoader = Thread.currentThread().getContextClassLoader();
ClassLoader loader = new URLClassLoader(urls, parentLoader);
Thread.currentThread().setContextClassLoader(loader);
歡迎來到世界的類加載器...您可以測試看到'Logic.class!= clazz' - 它們由不同的類加載器加載,所以它們是不同的類(即使它們具有相同的類名) – ZhongYu
有關 - http://stackoverflow.com/questions/30227510/sandbox-for-memory/30227614#30227614 – ZhongYu
@ bayou.io是的,它們是不同的類加載器,我想使原點類加載器識別的類動態地 – Gohan