I'm using java to do some thing as same as C++ Dynamic Library usage.
I didn't find the way to directly use the Same Class Object without reflect invoke style code.
this is my dynamic library code, I make it a jar.
package com.demo;
public class Logic {
public String doWork() {
System.out.println("Hello from Dll");
return "Dll";
}
}
In my main application, I can create the instance by URLClassLoader, invoke by reflect is fine:
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);
}
Output:
New Instance!!
Hello from Dll
But when I change the code without using 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();
}
}
Compile success(compile with external modules), but when I run the program, it failed at the line Logic logic = (Logic)clazz.newInstance();
Exception:
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
Is there any way to make it work? Without reflect/interface.(In C++ I can easily achieve this, share same struct/class declare, make sure using same compiler compile two parts. IMHO Java would do it also)
additional explanation 1
I want change the current classloader behavior to make it recognize the dynamic loaded class, this try is to simple and naive, can't find other direction:
ClassLoader parentLoader = Thread.currentThread().getContextClassLoader();
ClassLoader loader = new URLClassLoader(urls, parentLoader);
Thread.currentThread().setContextClassLoader(loader);