1

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

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

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

请参阅下图了解我在这里尝试做的事情。

在此处输入图像描述

我知道 M.jar 使用自定义 ClassLoader,因为它只需要将任何扩展名命名为 AE。

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

我想知道,

  1. 如果可以使用 APIUser 的 ClassLoader 加载 API 的类并初始化它以供 APIUser 使用。
  2. M 是否可以从任何其他扩展中阻止/隔离 API 的 ClassLoader?我认为它可以基于这个答案
  3. 还有什么其他方法可以在 APIUser1 或 APIUSer2 中加载 API 类......并且只维护 API 类的一个实例?(即单例)
4

1 回答 1

0

在对 ClassLoaders 进行了一些研究和研究之后,这就是我对我的问题的了解。

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

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

  3. 根据对问题 1 的回答,我现在要采用的方法是在运行时将 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

于 2018-06-18T01:47:03.010 回答