answers inline On 07.09.20 13:48, Manuel Souto Pico wrote: [...]
My Groovy script runs within a Java application (called OmegaT). This application extends its functionality by loading the jar files it finds in the /plugins folder of the installation. Even though they are optional and added/removed on demand, once the application runs, the jar files are loaded and become part of the running code that is being executed just as the code base of the application itself. My script downloads those jar files for the user and puts them in the /plugins folder.
ok, that makes much more sense to me now. But it sounds like a problem with class loaders... to illustrate it: m = new Map() m[X.class] = 1 then the class X, loaded through a class loader clx (example), can only be unloaded if neither X, nor clx are still referenced. But as long as the map m above exists, this is not the case and they stay in memory. in extension that means if X comes from X.jar, the class loader clx keeps the file X.jar open, till clx (and X) can be garbage collected
However, as there are updates in the jar files (and new versions normally have a different name), my script needs not only to download (and overwrite) the new ones but also delete the old ones. That's because, even though I'd think it should be easy for the application to sort what it finds and pick the one with the latest version number, in practice it seems that's not so easy -- the developers say the loading order is not guaranteed (it's up to the classpath loader to determine which one is used). To avoid that the application uses an old jar file instead of the new one, they should be deleted (i.e. my script's job).
sounds like the simple variant to load plugins. Not that this is wrong, it just does normally not support unloading plugins properly. And without that your usage scenario cannot work.
Now, why are they (normally) locked? I guess it is because the application loads them and opens them all when it is launched.
they are two simple variants. One is they are loaded together with all the other code of the application, like you said. the other is that there is a specific loader for the plugins, that is employed later for this. There are other solutions, but I doubt they are involved. Only in the second case you could have a chance, but it is unlikely
So, even though one version only is used in the end (if the application can see that they are different versions of the same plugin and picks only one), it seems all the jar files in the folder are (normally) loaded and locked. Which is, I think, what you mean in your last paragraph.
that works like this... def x = new X() this means to create an instance of X we first need to load the class X. To do this the current class loader (every class/script has one) is asked for the class X. A standard classpath class loader now goes through the jars, till it finds the class X. Now there is a fixed relation between the class X, that class loader and that specific jar. If there are other jars, that also have X, they are ignored. So if you have X-1.jar and X-2.jar it depends on the order of the lookup in the jars if X is taken from X-1.jar or X-2.jar. If the libraries have the same set of classes it is only a question of what version is used. But things can be a lot worse.
And your conclusion might be, unfortunately, correct. I had a hope that someone here could suggest a creative alternative. Either that, or the dirty hack I mentioned.
a switch to OSGI could solve the problem, but that is quite the change already. Without that the application would have to explicitly support this scenario and that is more or less difficult. It really depends on the application and requires a much more in detail look at the application to find out if that is even possible. Is the purpose of all this really to update jars while the application is running? Or do you need only to change something from the jars? bye Jochen