如何“关闭”ClassLoader?

时间:2011-09-20 15:45:25

标签: java urlclassloader

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

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

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

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

6 个答案:

答案 0 :(得分:7)

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

使用Java 7,URLClassLoader中添加了close()方法,这正是OP所要求的。

编辑(感谢@Hot Licks)好的,所以它不是完全 OP要求的内容。它不会释放所有资源,也不会使资源和加载程序具有收藏价值。它只是使用类加载器来阻止加载更多资源。然而, 关闭了使用URLClassLoader加载的jar文件。

答案 1 :(得分:4)

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

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

[请注意,删除对类的引用是一件非常重要的事情。任何其他按名称引用它的类当然会阻止删除。因此必须使用ClassLoader.findClass或类似的东西加载类。]

答案 2 :(得分:3)

如果您不再从该类加载器加载类(和对象),并且如果您没有保留对该类加载器的任何引用,它将由垃圾收集器自动处理。

答案 3 :(得分:3)

如果您不能使用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;
}

答案 4 :(得分:1)

URL类加载器或其任何父类中没有close()方法,所以你运气不好。

GC不应该处理这个吗?

答案 5 :(得分:0)

我扩展了URLClassLoader,并基于Java 7s创建了一个close方法。我想在我的iPad 2上开发我的IRC机器人,所以我做了我需要的东西。现在我的插件系统在Java 6和7上是稳定的,欢呼。