当前位置: 首页 > 知识库问答 >
问题:

如何使用公共抽象类动态加载jar?

皇甫飞飙
2023-03-14

我正在尝试开发一个插件系统,它提供了一个在运行时加载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)。这个罐子只包含插件A.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)

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

共有2个答案

蓬英逸
2023-03-14

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

URLClassLoader ClassLoader = URLClassLoader.newInstance(new URL[] {url},
                                                        this.getClassLoader());
龙兴贤
2023-03-14

由于它是一个非法访问错误,我建议你公开BasicPlugin来解决问题。据我所知,您定义的类是包保护的。因此,无法从不同的类装入器访问它。由于这是您的插件所需要的,因此使类公开之外没有任何意义。

还有一件事,URLClassLoader有第二个构造函数,您可以在其中指定父加载器。然后使用此加载器加载插件类。在更复杂的环境中,您可能需要指定该加载器。目前,您的代码或多或少使用了系统加载器,这在您的示例中是可以的,但我不知道您稍后打算做什么。BasicPlugin.class.getClassLoader()无疑为该类提供了正确的加载器。

 类似资料:
  • 嗨,我有一个抽象类,其中有一些公共方法和一些抽象方法。我让公众知道,他们实现了派生类的通用方法。 让我困惑的是,为什么我想定义一个公共抽象方法,而不是受保护的抽象方法。在抽象类中定义公共抽象方法对我来说毫无意义。。。。因为if是一个抽象,在派生类中会被重写,但if被定义为public也是一样的,但在某种程度上,将其定义为protected更有意义,因为我们知道,我们将在派生类中重写它。 在抽象类中

  • 我有一个抽象类的许多子类,每个子类都声明了一个同名的公共静态final字段。我在考虑在抽象超类中包含这个字段,而不初始化它,并希望每个子类都能被强制初始化它。 我之所以这么想,是因为抽象类的所有子类都声明了一个名为UNIQUE_ID的公共静态最终字符串字段,并且每个子类都有必要声明一个具有该名称的字段。 我希望我的问题足够清楚,如果不清楚,请告诉我。 能不能做一些和这个差不多的事情? 编辑:添加代

  • 如何调用从公共静态空白到非静态的公共空白碎片类?或者有另一种方法在(listViewHolder.dot.setOnClickListener(new View.OnClickListener()和公共无效搜索3())

  • 我得到了一个抽象类: 和两个自动生成的子类: 以及一个用于创建网络模式(请求/回复)的应用编程接口,该模式使用请求类型和回复类型(A和B预计将像上述那样是自动生成的FOPACImpl子类): 我从XML存根中提取主题字符串,以及两种类型A和B的字符串名称: 显然,Java中的反射不能直接处理“公共抽象”超类? 结果 1) 为什么“使用“受保护”的修饰符”?FooPACImpl。getClass()

  • 问题内容: 我查找了语法并搜索了api,但仍然对该过程感到困惑。我还搜索了Stackoverflow。加载类并从中动态创建对象的正确方法是什么?换句话说,我希望用户指定要创建的对象类型,然后创建该类型的对象。我不需要菜单,因为我希望他们能够选择当前目录中的任何类。 问题答案: 假设该类具有无参数构造函数,则最简单的方法是- 参考-java.lang.Class

  • 在谷歌代码上提供的ehcache spring注解库中,一个配置选项“创建缺少的缓存”可用于动态创建缓存(缓存未在ehcache.xml中定义)。纯spring ehcache抽象(spring 3.1.1)中是否有类似的配置?或者有没有其他方法可以使用spring ehcache抽象创建动态缓存?

  • 问题内容: 请查看下面的修改 我正在尝试创建一个 JShell实例 ,该 实例 使我可以访问它,并让我与创建它的 JVM中的 对象进行交互。这对于在编译时可用的类很好,但对于 动态 加载的类却失败了。 另外,与交换可以得到相同的结果,但是我不理解两个类之间的区别。 如何使 运行时 加载的类可用于此 JShell实例 ? 编辑:此问题的第一部分已解决,下面是更新的源代码,以演示问题的第二部分 如果

  • 我最近遇到了以下方法。我试着用谷歌搜索,并通过定义如下方法,做了一个例子来了解差异;两者似乎是一样的。但是,我需要知道它是否真的是一样的? 注意:在以上两种方法中,公共代码和抽象代码已经互换。