如何用常见的抽象类动态加载jar?

我正在尝试开发一个插件系统,它提供了一个在运行时加载jar的接口。 每个jar包含一个从公共抽象类扩展的类。 例如:

//BasicPlugin.java package byv; abstract class BasicPlugin { abstract public int test(int a); } 

我实现了一个子类:

 //PluginA.java package byv; import byv.BasicPlugin; public class PluginA extends BasicPlugin { @Override public int test(int a) { return a + a; } } 

上面的子类被编译并打包到一个jar文件(PluginA.jar)中。 这个jar只包含PluginA.class。 然后在主项目中我使用URLClassLoader加载它:

 private static void loadTest() throws Exception { URL url = new File("PluginA.jar").toURI().toURL(); URLClassLoader ClassLoader = URLClassLoader.newInstance(new URL[] {url}); Class clazz = Class.forName("byv.PluginA", true, ClassLoader); BasicPlugin obj = (BasicPlugin) clazz.newInstance(); obj.test(2); } 

我已经在主项目中添加了对BasicPlugin的引用。 但错误仍然存​​在:

 Exception in thread "main" java.lang.IllegalAccessError: class byv.PluginA cannot access its superclass byv.BasicPlugin at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:634) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) at java.net.URLClassLoader.defineClass(URLClassLoader.java:277) at java.net.URLClassLoader.access$000(URLClassLoader.java:73) at java.net.URLClassLoader$1.run(URLClassLoader.java:212) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:205) at java.lang.ClassLoader.loadClass(ClassLoader.java:321) at java.net.FactoryURLClassLoader.loadClass(URLClassLoader.java:615) at java.lang.ClassLoader.loadClass(ClassLoader.java:266) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:264) at byv.Main.loadTest1(Main.java:18) at byv.Main.main(Main.java:11) 

那么我该如何解决这个问题呢?

由于它是IllegalAccessError,我建议你公开BasicPlugin来解决问题。 Afaik你定义的类是包保护的。 因此,无法从不同的类加载器访问它。 既然这就是你的插件所需要的,那么让这个课程比公开的更有意义。 还有一件事,URLClassLoader有第二个构造函数,您可以在其中指定父加载器。 然后使用此加载器加载插件类。 在更复杂的环境中,您可能希望指定该加载器。 目前你的代码使用或多或少的系统加载器,这在你的例子中是可以的,但我不知道你打算以后做什么。 BasicPlugin.class.getClassLoader()确实为您提供了该类的正确加载器。

传递类加载器上下文以在构造URLClassLoader实例时使用:

 URLClassLoader ClassLoader = URLClassLoader.newInstance(new URL[] {url}, this.getClassLoader());