Jaikiran Pai wrote:
Jaikiran Pai wrote:Windows OS has some known issues with this kind of file locking.
See this and the JDK bug referenced in that blog.
Paul Clapham wrote:
Frank Martin Carl wrote:I've developed a simple JarFileLoader using URLClassLoader.
Now I would like it to reload new JAR files and free the old ones, but it seems URLClassLoader locks the JAR files and won't release them until the JVM is closed.
In the application I use which does that, this is the process they use: they watch for changes in the JAR file. When they see one, they copy the JAR file to a temporary directory and use that, I assume via a URLClassLoader. That way they don't care whether the temporary copy remains locked after they stop using it.
Ernest Friedman-Hill wrote:Frank,
Since JarClassLoader is your own class, we can't vouch for how it behaves. Does it open or close jar files for reading by itself? Or does this happen only in the parent URLClassLoader? Maybe we could see the JarClassLoader code.
Ulf Dittmer wrote:It seems that that should work. Of course, it only would work if the classloader really did get garbage-collected. Try calling System.gc() 5 times in a row, then putting the thread to sleep for a few seconds, and then try to delete the file. That might give the JVM some extra time and inclination to perform a GC.
Ulf Dittmer wrote:
But, how can I discard the classloader? Setting it to null doesn't work: jar files are still locked.
This may go without saying, but you also need to make sure that all classes that have been loaded through that classloader are also eligible for garbage collection (meaning that none of their objects are still referenced from anywhere in your code, like in a collection).
Ulf Dittmer wrote:This may be more work than you want to embark upon (although it pays back in the long run), but this sounds like a perfect application for an OSGi container like Apache Felix.
Ernest Friedman-Hill wrote:Since the very beginning of Java, there has been one way, and one way only, to unload a class: by discarding the ClassLoader that loaded it. Normally, this works just fine. For example, when a servlet container reloads a web app, it discards the classloader that originally loaded that app, creates a new one, and loads it anew. So that's basically what you need to do.