Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I "close" a ClassLoader?

I have a case where I need to create a lot of class loaders in my application to temporarily make some code visible while user supplied scripts are running. I'm using an URLClassLoader for this and it works pretty well.

When the script terminates, I want to "unload" or "close" the class loader to free the resources.

Is it enough to set the reference to the class loader to null? I'm especially wondering if I'll eventually run out of file handles because the extra classes are in JAR files.

PS: Must work with Java 5 and up. Yeah, I know...

like image 549
Aaron Digulla Avatar asked Sep 20 '11 15:09

Aaron Digulla


People also ask

How does the ClassLoader work?

A Java Class is stored in the form of byte code in a . class file after it is compiled. The ClassLoader loads the class of the Java program into memory when it is required. The ClassLoader is hierarchical and so if there is a request to load a class, it is delegated to the parent class loader.

What is extension ClassLoader?

Extension ClassLoader: The Extension ClassLoader is a child of Bootstrap ClassLoader and loads the extensions of core java classes from the respective JDK Extension library. It loads files from jre/lib/ext directory or any other directory pointed by the system property java. ext. dirs.

What is ClassLoader in JVM?

Class loaders are responsible for loading Java classes dynamically to the JVM (Java Virtual Machine) during runtime. They're also part of the JRE (Java Runtime Environment). Therefore, the JVM doesn't need to know about the underlying files or file systems in order to run Java programs thanks to class loaders.


5 Answers

A little late, but hopefully this'll be helpful for those who come to this Question later (like me).

With Java 7, a close() method has been added to URLClassLoader, which is exactly what OP was asking for.

EDIT (thanks to @Hot Licks): OK, so it isn't exactly what the OP has asked for. It doesn't free up all the resources, or make the resources and the loader collectible. It simply prevents the loading of more resources using the class loader. It does, however, close the jar file that was loaded with the URLClassLoader.

like image 130
aspiring_sarge Avatar answered Oct 05 '22 06:10

aspiring_sarge


If you can't use Java7 and it's close() method, use reflection to close all open JAR archives of a classloader, like so:

public void close() {
try {
   Class clazz = java.net.URLClassLoader.class;
   java.lang.reflect.Field ucp = clazz.getDeclaredField("ucp");
   ucp.setAccessible(true);
   Object sun_misc_URLClassPath = ucp.get(this);
   java.lang.reflect.Field loaders = 
      sun_misc_URLClassPath.getClass().getDeclaredField("loaders");
   loaders.setAccessible(true);
   Object java_util_Collection = loaders.get(sun_misc_URLClassPath);
   for (Object sun_misc_URLClassPath_JarLoader :
        ((java.util.Collection) java_util_Collection).toArray()) {
      try {
         java.lang.reflect.Field loader = 
            sun_misc_URLClassPath_JarLoader.getClass().getDeclaredField("jar");
         loader.setAccessible(true);
         Object java_util_jar_JarFile = 
            loader.get(sun_misc_URLClassPath_JarLoader);
         ((java.util.jar.JarFile) java_util_jar_JarFile).close();
      } catch (Throwable t) {
         // if we got this far, this is probably not a JAR loader so skip it
      }
   }
} catch (Throwable t) {
   // probably not a SUN VM
}
return;
}
like image 32
chaity Avatar answered Oct 05 '22 06:10

chaity


When all classes that the class loader loaded no longer have any references, and all references to the class loader itself have been erased, the class loader and the classes it loaded will be garbage collected as a group.

Note that this is dependent on having the JVM attribute set that causes unreferenced classes to be unloaded. It's set by default in most environments, but may not be in some embedded cases.

[Note that it's a non-trivial matter to remove references to a class. Any other class that references it by name will of course prevent removal. So the class must be loaded using ClassLoader.findClass or something similar.]

like image 25
Hot Licks Avatar answered Oct 05 '22 08:10

Hot Licks


If you do not longer have classes (and object) loaded from that classloader, and if you do not keep any reference to that classloader, it will automatically handled by the garbage collector.

like image 41
Matteo Avatar answered Oct 05 '22 06:10

Matteo


There are no close() methods in URL class loader or any of its parent classes, so you're out of luck.

Shouldn't GC handle this?

like image 23
duffymo Avatar answered Oct 05 '22 06:10

duffymo