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

时间:2018-06-11 00:44:50

标签: java jar classloader dynamic-class-loaders serviceloader

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

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

  1. 编写扩展API1并将其加载到M。
  2. 编写另一个扩展APIUser,将其加载到M并使用API​​1。
  3. 请参阅下图,了解我在这里要做的事情。

    enter image description here

    我知道M.jar使用自定义ClassLoader,因为它要求任何扩展名仅限AE。

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

    我想知道,

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

1 个答案:

答案 0 :(得分:0)

经过一些研究和研究ClassLoaders,这是我对我的问题所学到的。

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

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

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

  4. 注意:我还假设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