如何"关闭"ClassLoader?

Aar*_*lla 10 java urlclassloader

我有一个案例,我需要在我的应用程序中创建许多类加载器,以便在用户提供的脚本运行时暂时显示一些代码.我正在使用URLClassLoader它,它的效果非常好.

当脚本终止时,我想"卸载"或"关闭"类加载器以释放资源.

是否足以将类加载器的引用设置为null?我特别想知道我是否最终会用完文件句柄,因为额外的类在JAR文件中.

PS:必须使用Java 5及更高版本.是的,我知道...

asp*_*rge 7

有点晚了,但希望这对以后来这个问题的人(比如我)有帮助.

在Java 7中,URLClassLoader中添加了一个close()方法,这正是OP所要求的.

编辑(感谢@Hot舔): OK,所以它不是确切什么OP已经要求.它不会释放所有资源,也不会使资源和加载程序具有收藏价值.它只是使用类加载器来阻止加载更多资源.但是,它确实关闭了加载了的jar文件URLClassLoader.


小智 5

如果您不能使用 Java7 并且它是 close() 方法,请使用反射来关闭类加载器的所有打开的 JAR 档案,如下所示:

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;
}
Run Code Online (Sandbox Code Playgroud)


Hot*_*cks 4

当类加载器加载的所有类不再有任何引用,并且类加载器本身的所有引用都已被删除时,类加载器及其加载的类将作为一个组被垃圾收集。

请注意,这取决于 JVM 属性集是否导致未引用的类被卸载。在大多数环境中它是默认设置的,但在某些嵌入式情况下可能不是。

[请注意,删除对类的引用并不是一件简单的事情。任何其他通过名称引用它的类当然都会阻止删除。因此必须使用 ClassLoader.findClass 或类似的方法加载该类。]