简体   繁体   中英

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. The application requires that the classes implement interface E and be called NE.

Now, the following is what I'm trying to do,

  1. Write an extension API1 and load it to M.
  2. Write another extension APIUser, load it to M and make use of API1.

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.

I tried the ServiceProvider, ServiceProviderInterface method as described here but that did not work. I believe this is because API's classes are not in M's classpath and hence APIUser cannot find it.

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.
  2. Is it possible for M to block/isolate API's ClassLoader from any other extensions? 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? (ie singleton)

After some researching and studying up ClassLoaders, here's what I've learnt regarding my questions.

  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. 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. This means that classes loaded from API.jar are not visible in APIUser.jar.

  2. M doesn't explicitly isolate extensions but it is the natural way of loading JARs into an application.

  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. This is because the SystemClassLoader is visible from any extensions.

NOTES: I'm also assuming that the ServiceLoader way of doing this would also work. But I've not tried it myself.

References:

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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