2

I have a series of folders that contain JAR files, these JARs act as plugins for my main application. Each seperate folder of JARs is loaded with its own classloader, so that that folder of JARs can be loaded and unloaded independantly of other folders.

Some JARs have dependencies on other JARS. In several cases there are multiple JARs (Say, Set A) that have a dependency on the same seperate JAR (Lets call it BaseJar). For this reason I have a seperate folder for this BaseJar, so that I can just load it the once and not have multiple places where the JAR could exist.

I need to provide the functionality where any one of these sets of JARs could be disabled, and then reloaded. So that any small updates to these plugins can be done on the fly without having to disable the entire application. This leads me to the question in my title. If I were to unload this BaseJar class, so that it could be updated, is there a way to avoid then having to unload and reload all of the SetA JARs as well? I would like them to be able to continue to operate as normal as soon as their new dependency has been loaded by the seperate class loader.


EDIT: To clarify my position, after some answers have been given, I already have a working custom JarClassLoader. At present I can load up all of my plugins and unload them all just fine. I need to know whether it's possible for me to load and unload in batches, without affecting other JARs that may use some class contained in another JAR which gets upgraded at runtime.

I'm aware there may be issues if I attempted to use that plugin during the upgrade process, where the class it's attempting to use is no longer loaded by the JVM and therefore unavailable until the newer version has been loaded. It's just after this new class has been uploaded, will it possibly lead resolution problems?

Seb
  • 959
  • 16
  • 29

1 Answers1

0

Jar only contains class file. It is not really a question of dependancy, but rather

  • 1 the question of loading the JAR you want (the classes you want)

  • and 2, unloading one and replace

  • and 3, then manage objects from classes in these JAR

1 For loading, and reloading a JAR, see that, by changing your classpath: Can I dynamically unload and reload (other versions of the same) JAR?

the code:

 // jarFile is the version of the jar you want to use/overwrite.

  URLClassLoader urlClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();

    Method m = URLClassLoader.class.getDeclaredMethod("addURL", new  Class[]{URL.class});
    m.setAccessible(true);
    m.invoke(urlClassLoader, jarFile.toURI().toURL());
    String cp = System.getProperty("java.class.path");
    if (cp != null) {
        cp += File.pathSeparatorChar + jarFile.getCanonicalPath();
    } else {
        cp = jarFile.toURI().getPath();
    }
    System.setProperty("java.class.path", cp);

Beware of what can happens: read that: Why can't System.setProperty() change the classpath at runtime?

and read these warnings: Why can't System.setProperty() change the classpath at runtime?

If you do that before to load the class you want, it's OK.

If not, it's more difficult:

2 and 3: you should not have an object of the "old" classes when you do the change, or the result should be unpredictable. It's the responsability of your program to get rid of it, and the classloader.

See this, which advise to create its own ClassLoader, for each Jar

Unloading classes in java?

Community
  • 1
  • 1
  • As far as actually loading and unloading the JARs go, I think the resources on Stackoverflow are already very clear, and I have a working JarClassLoader already. You say my question is not one of dependency, but it really is. I already have my JARs loaded and unloaded, I now need to know if it's possible for JARs to resolve dependencies on class files inside other JARs that get unloaded then reloaded to newer versions. – Seb Dec 08 '15 at 12:02
  • @Seb I said It's not REALLY a question of dependancy. If you know exacly which JAR and classes inside needs which other JAR/classes, then you should implement in each one your logic of dependancy, by loading the good one. – guillaume girod-vitouchkina Dec 08 '15 at 12:05
  • Yes, I realise this, and I do load them. My question revolves around whether after I unload and then load a new modified version of this class, that another JAR uses, will this JAR be able to resolve access to this updated class? Will it need to be reloaded itself to see this updated class, or does this resolution happen when necessary in the JVM? – Seb Dec 08 '15 at 12:09
  • see this also: http://stackoverflow.com/questions/6105124/java-classpath-classloading-multiple-versions-of-the-same-jar-project - it is based on classes (and package), not on JAR. these loadings are independants normally. – guillaume girod-vitouchkina Dec 08 '15 at 12:16
  • Hmm, I'm not concerned with keeping two versions of the sameclass running at once, but i think I can see the point you're trying to make. My question can essentially be reduced to 'When, and how, does one class resolve if it can access another class in the JVM'. But I can't find a conclusive answer for that question either. – Seb Dec 08 '15 at 12:35