java - 如何从 JAR 应用程序中动态加载类以在另一个 JAR 中使用?

标签 java jar classloader dynamic-class-loaders serviceloader

我有一个 JAR 应用程序 M.jar,它支持动态编写和加载扩展。应用程序要求类实现接口(interface) E 并称为 NE。

现在,以下是我正在尝试做的事情,

  1. 编写扩展 API1 并将其加载到 M。
  2. 编写另一个扩展 APIUser,将其加载到 M 并使用 API1。

请参阅下图了解我在这里尝试执行的操作。

enter image description here

我知道 M.jar 使用自定义类加载器,因为它要求任何扩展名仅命名为 AE。

我尝试了 ServiceProvider、ServiceProviderInterface 方法,如所述 here但这没有用。我相信这是因为 API 的类不在 M 的类路径中,因此 APIUser 找不到它。

我想知道

  1. 是否可以使用 APIUser 的 ClassLoader 来加载 API 的类并初始化它以便在 APIUser 中使用。
  2. M 是否可以阻止/隔离 API 的类加载器与任何其他扩展?我认为它可以基于 this answer .
  3. 还有什么其他方法可以在 APIUser1 或 APIUSer2 中加载 API 类...并仅维护 API 类的一个实例? (即单例)

最佳答案

经过对类加载器的一些研究和学习,以下是我对我的问题的了解。

  1. 这是无法完成的,因为 M.jar 和其他可扩展 Java 程序加载另一个程序的方式是使用 URLClassLoader 作为其他某个 ClassLoader 的子级。这意味着在 ClassLoader 委托(delegate)层次结构中,API.jar 的 ClassLoader 位于层次结构中的较高位置,而 APIUser.jar 的 ClassLoader 将是同级。这意味着从 API.jar 加载的类在 APIUser.jar 中不可见。

  2. M 没有明确隔离扩展,但它是将 JAR 加载到应用程序中的自然方式。

  3. 根据问题 1 的答案,我现在要做的方法是使用 hackish在运行时将 JAR 添加到 SystemClassLoader 的类路径,然后通过使用 SystemClassLoader 加载它从其他/任何扩展引用它的方法。这是因为 SystemClassLoader 从任何扩展中都是可见的。

注释:我还假设 ServiceLoader 执行此操作的方式也可以工作。但我自己没有尝试过。

引用文献:

https://zeroturnaround.com/rebellabs/rebel-labs-tutorial-do-you-really-get-classloaders/

https://docs.oracle.com/javase/8/docs/api/java/lang/ClassLoader.html

关于java - 如何从 JAR 应用程序中动态加载类以在另一个 JAR 中使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50789278/

相关文章:

java - GWT、Google App Engine、TimerTask 或 ServiceImpl 中的 Thread 抛出异常

java - Spring无法添加外键约束@​​ManyToOne

java - ProGuard 破坏了对我的 Java 小程序的 javascript 访问

java - 无法找到或加载主类 cmd,它在 Eclipse 中工作正常,构建路径似乎没问题

java - activeMQ 如何能够执行不在其类路径中的类

java - 系统类加载器的名称

java - 阿克曼函数

java - 如何从java中执行带文件名的jar命令

Java:更新 jar 文件时加载类

java - 在这种情况下,是否会在同一个 JVM 实例中加载同一个类两次?