How to unload Java Class
By Angsuman Chakraborty, Gaea News NetworkTuesday, March 15, 2005
I have been asked this question several times. Recently Xyling asked the same question in his blog. So I thought a simple explanation may be in order.
To unload a class you have to create a custom classloader and load the class using it. Tomcat does it and so does JRun. You can look in Tomcat code for an example.
After you are done with the class you need to release all references to the class as well as to the class loader by reassigning the variables or setting them to null.
Then either wait for System.gc() to unload the class or you call it directly in a loop till no more bytes can be freed. however normally calling it twice does the trick.
Note: You cannot unload a single class. You have to unload the classloader along with it. So obviously System classloader is not the suitable for this task.
Note 2: This is how JSP pages are reloaded dynamically everytime you change the code. And yes that is why first time takes much longer to load then subsequent times.
September 11, 2006: 11:39 am
Thanks for the information. I read something on the internet which I think is important for some people here: Two classes are not of the same package if they are loaded by different ClassLoader objects! So if you planned to make a new ClassLoader object for every class, consider using one ClassLoader object for each package. The other option is to make all classes public. |
April 1, 2005: 6:02 am
@Sandip Why not use the URLClassLoader? Also there is a sample ClassLoader code provided in Java Tutorials. |
![]() sandip |
March 23, 2005: 6:23 pm
it’s great information that how plugins are works. Can i have the simplest possible code of custom class loader. Ultimately the custom class loader is nees to be loaded by the default classloader or not? If so then will i be able to see to classloader in the callgraph of such kind of program? |
March 22, 2005: 7:35 pm
Kevin, It’s true that you can’t null the reference to the interface class ( Class#getInterfaces() ), if this was possible it would mean that you remove the interface in the byte code at runtime, from: public class MyTestImpl implements TestImpl to public class MyTestImpl The same is true for superclasses. |
![]() Kevin |
March 19, 2005: 2:54 am
Goldy Lukka, The trick to using URLClassLoader to reload or unload .jar files is making sure that NO other code is referencing any of the classes within the .jar file. Dependencies are difficult to manage. We have gone to great pains to try to resolve unload/reload with the issue of plugins depending on one another. We still have problems in many cases making it happen. In some cases, developers of plugins just have to be aware that if they want to make their plugin as dynamic as possible, they really have to develop it in such a way that they properly clean up any references they have on other plugin classes. If your .jar file is just adding implementations to say, a core applications interface API, you should be able to easily remove it. As we discovered, an implemting class keeps a reference (lock) on the interface it implements. So the class in your .jar file would keep the ref to the interface, which is ok, you simply null it out and/or null the classloader that loaded the .jar and you are fine. If however the .jar file provides interfaces that other classes (maybe from other .jar files) make use of, that becomes more difficult. Any class outside of the classloader that loaded the .jar file making use of any class from inside the loaded .jar has to also be unloaded. Again, referring to our engine, it starts a chain reaction of unloading events that can be difficult to manage. We solved the problem by having two classloader instances per plugin. One that handles the interfaces that are implemented by other plugin classes, and one for the rest of the classes. It’s not pretty, but thus far it works. We are still experimenting to make this a better process. |
March 18, 2005: 3:00 am
@Goldy Lukka Yes. You should be able to. However I haven’t used URLClassLoader in this fashion, so I am not sure if it has any hard-to-remove references. I guess a spike solution is in order @Kevin Thanks for the very informative comment. |
![]() Kevin |
March 16, 2005: 4:28 pm
If you are interested in seeing an interesting twist on dynamic reloading of classes, check out the source in our plugin engine at https://www.platonos.org. We not only load plugins, each with their own classloader, but we are now adding the ability to dynamically unload portions of a plugin that are dependent on another. As it turns out, when plugin A provides an interface that plugin B provides an implementation for, the plugin B ClassLoader (through delegation to A’s classloader) holds a lock on the implementation Class itself. Even after we null out the classloader in plugin A (if we are trying to unload A), B’s classloader keeps a lock on A because of the interface Class that B’s implementation class keeps a lock on. Basically you have this: interface pluginAInterface{} class pluginBImpl implements pluginAInterface{} each is loaded by a different classloader. When used, plugin B’s classloader sees that pluginBImpl implements pluginAInterface. It starts in plugin B’s classloader looking for it. It can’t find it there (because the pluginAInterface Class is in plugin A’s classloader classpath). The plugin engine delegates the lookup to plugin A’s classloader to find the byte code for this pluginAInterface Class. It’s found there, so plugin A’s classloader “loads” the bytecode, but plugin B’s classloader “sees” the bytecode by initially delegating to A to find it. Once found, a classloader’s built in cache stores the classloader:class pointer (meaning, the classloader AND the class make up a sort of “key” as a pointer to the actual bytecode in memory) so it no longer needs to delegate to A. BUT, the big problem is that the pluginBImpl Class maintains it’s own list of interfaces it implements, primarily their Class reference. The bad thing about this is there is no way to set this to null at runtime! It’s a bit tricky, but it does the trick. Probably still more hidden issues we haven’t come across yet. |
![]() Jed Wesley-Smith |
March 15, 2005: 6:41 pm
Actually, the JSP first-load time is not ONLY due to the class being reloaded, (loading a class from the bytecode doesn’t take that long, if it did Java would be a lot slower than it is ;-). A more significant amount of time is spent generating the bytecode, as a change to the JSP source has to be converted first into Java source, and then in to byte-code, which can then be loaded by the ClassLoader. So, add two parse/generate cycles to one byte load… |
March 15, 2005: 6:31 pm
Hi, Thank you very much for this information. |
Paul Breeuwsma