简体   繁体   English

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

[英]How to dynamically load class from within a JAR application for use in another JAR?

I have a JAR application, M.jar that supports extensions to be written and loaded dynamically. 我有一个JAR应用程序M.jar,它支持动态编写和加载的扩展。 The application requires that the classes implement interface E and be called NE. 该应用程序要求这些类实现接口E并称为NE。

Now, the following is what I'm trying to do, 现在,以下是我正在尝试做的事情,

  1. Write an extension API1 and load it to M. 编写扩展API1并将其加载到M。
  2. Write another extension APIUser, load it to M and make use of API1. 编写另一个扩展APIUser,将其加载到M并使用API​​1。

Please see below diagram for what I'm trying to do here. 请参阅下图,以了解我在这里要做的事情。

在此处输入图片说明

I know that M.jar uses a custom ClassLoader because it requires any extension be named AE only. 我知道M.jar使用自定义的ClassLoader,因为它要求将任何扩展名仅命名为AE。

I tried the ServiceProvider, ServiceProviderInterface method as described here but that did not work. 我按此处所述尝试了ServiceProvider,ServiceProviderInterface方法,但是没有用。 I believe this is because API's classes are not in M's classpath and hence APIUser cannot find it. 我相信这是因为API的类不在M的类路径中,因此APIUser无法找到它。

I want to know, 我想知道,

  1. If it is feasible to use APIUser's ClassLoader to load API's class and initialize it for use in APIUser. 如果可行,则使用API​​User的ClassLoader加载API的类并对其进行初始化以供在APIUser中使用。
  2. Is it possible for M to block/isolate API's ClassLoader from any other extensions? M是否有可能将API的ClassLoader阻止/隔离于其他任何扩展? I think it can be based off of this answer . 我认为可以基于此答案
  3. What other means are there to load API's class in APIUser1 or APIUSer2 ... and maintain only one instance of API's class? 还有什么其他方法可以将API的类加载到APIUser1或APIUSer2 ...中,并且仅维护API的类的一个实例? (ie singleton) (即单例)

After some researching and studying up ClassLoaders, here's what I've learnt regarding my questions. 在对ClassLoader进行了一些研究和研究之后,这就是我对问题的了解。

  1. This can't be done because that way M.jar and other extensible Java programs load another is using URLClassLoader as a child of some other ClassLoader. 之所以不能这样做,是因为M.jar和其他可扩展Java程序加载另一个方法是将URLClassLoader用作其他ClassLoader的子级。 This means in the ClassLoader delegation hierarchy, API.jar's ClassLoader sits higher in the hierarchy and APIUser.jar's ClassLoader would be a sibling. 这意味着在ClassLoader委托层次结构中,API.jar的ClassLoader在层次结构中位于较高的位置,而APIUser.jar的ClassLoader将是同级的。 This means that classes loaded from API.jar are not visible in APIUser.jar. 这意味着从API.jar加载的类在APIUser.jar中不可见。

  2. M doesn't explicitly isolate extensions but it is the natural way of loading JARs into an application. M并未明确隔离扩展,但它是将JAR加载到应用程序中的自然方法。

  3. Based on the answer to question 1, the way I'm going about it right now is using the hackish way of adding the JAR to SystemClassLoader's classpath at runtime and then referring to it from the other/any extensions by loading it using the SystemClassLoader. 基于问题1的答案,我现在要解决的方法是使用在运行时将JAR添加到SystemClassLoader的类路径中的怪诞方式,然后通过使用SystemClassLoader加载它来从其他/任何扩展中引用它。 This is because the SystemClassLoader is visible from any extensions. 这是因为从任何扩展名都可以看到SystemClassLoader。

NOTES: I'm also assuming that the ServiceLoader way of doing this would also work. 注意:我还假设使用ServiceLoader进行此操作也可以。 But I've not tried it myself. 但是我自己还没有尝试过。

References: 参考文献:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM