wood burning stoves 2.0*
The moose likes Java in General and the fly likes URLClassLoader won't free JAR files Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Murach's Java Servlets and JSP this week in the Servlets forum!
JavaRanch » Java Forums » Java » Java in General
Bookmark "URLClassLoader won Watch "URLClassLoader won New topic
Author

URLClassLoader won't free JAR files

Francesc Martinez
Greenhorn

Joined: Feb 13, 2009
Posts: 24
Hello,

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.

I've read that, In Java 7, they're going to add the Closeable.close() method to URLClassLoader but, in the meantime, as to Java 5, is there any way to release the loaded JAR files? Or do you know any other class/API that lets you do it (from Apache perhaps? They need to do it in Tomcat!).

Thank you very much!!!
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24183
    
  34

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.


[Jess in Action][AskingGoodQuestions]
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 41034
    
  43
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.


Ping & DNS - my free Android networking tools app
Francesc Martinez
Greenhorn

Joined: Feb 13, 2009
Posts: 24
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.


But, how can I discard the classloader? Setting it to null doesn't work: jar files are still locked.
Francesc Martinez
Greenhorn

Joined: Feb 13, 2009
Posts: 24
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.


I don't know much about OSGi; I've read it's about services.

Do you mean I could start a service (with some jars) so later I could restart that service (when I need to update the jars)?
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 41034
    
  43
I don't know much about OSGi; I've read it's about services.

Services are part of it, but it's a very broad-based framework that can be used for may purposes. You can find some introductory articles linked in http://faq.javaranch.com/java/OSGiLinks

Do you mean I could start a service (with some jars) so later I could restart that service (when I need to update the jars)?

Yes, that's a common use case for OSGi. There are several ways in which this could work: either the app user could click a button/menu that causes the service to be discarded and reloaded, or the app could be set up to monitor a directory that contains the jar files and trigger the reloading automatically whenever there's a change, or the service code could monitor itself and notify the host app that it should trigger a reload if a file changes.
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 41034
    
  43
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).
Francesc Martinez
Greenhorn

Joined: Feb 13, 2009
Posts: 24
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).


That's not the problem, I think. I've written a small program where I create a URLClassLoader, I add a jar to it and then load a class from that jar (I just call loader.loadClass(), ignoring the returned class and not instantiating it). Then, after nulling the URLClassLoader... the jar file is still locked.

This is pseudocode of what I did:



Now, before exiting the program, I try to delete "some.jar", but it's locked!
Ulf Dittmer
Marshal

Joined: Mar 22, 2005
Posts: 41034
    
  43
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.
Francesc Martinez
Greenhorn

Joined: Feb 13, 2009
Posts: 24
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.


Hehe, that seems like a witch recipe!
I'd like to find something more "scientific".

Anyway, I'll try it. Thanks!
Ernest Friedman-Hill
author and iconoclast
Marshal

Joined: Jul 08, 2003
Posts: 24183
    
  34

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.
Francesc Martinez
Greenhorn

Joined: Feb 13, 2009
Posts: 24
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.


Here is the code:

Maneesh Godbole
Saloon Keeper

Joined: Jul 26, 2007
Posts: 10167
    
    8

Frank Martin Carl wrote:


Please check your private messages for an important administrative matter


[How to ask questions] [Donate a pint, save a life!] [Onff-turn it on!]
Paul Clapham
Bartender

Joined: Oct 14, 2005
Posts: 18541
    
    8

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.
Francesc Martinez
Greenhorn

Joined: Feb 13, 2009
Posts: 24
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.


Great idea Paul, thanks!

The only problem is those temporary copies will be locked. But it's the best solution I've seen so far.
Jaikiran Pai
Marshal

Joined: Jul 20, 2005
Posts: 9912
    
158

Which operating system are you testing this on? Windows OS has some known issues with this kind of file locking. If you have access to some *nix system, try the same code over there.


[My Blog] [JavaRanch Journal]
Jaikiran Pai
Marshal

Joined: Jul 20, 2005
Posts: 9912
    
158

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.
Francesc Martinez
Greenhorn

Joined: Feb 13, 2009
Posts: 24
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.


Great article, thank you very much!

By the way, I'm using Windows (although the article says it will happen also with UNIX).
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: URLClassLoader won't free JAR files
 
Similar Threads
Jar Question
loading jar dynamically
Final Packaging Structure
specifying additional jars at runtime
Good server for learning EJB