我正在玩Java中的classLoaders并注意到一件奇怪的事情。如果classLoader从jar加载一个类,即使你没有引用你的classLoader,这个jar也会被无限期锁定。
在下面的示例中,jar包含一个名为HelloWorld的类。我所做的是尝试通过classLoader加载jar中包含的类,该类动态地添加jar。如果您将skip
设置为true
而不是致电Class.forName
,则可以删除该jar,但如果您不跳过,即使您不引用classLoader
({{1}在JVM退出之前,无法删除jar。
为什么?
PS:我使用的是java 6,代码非常冗长,用于测试目的
classLoader = null
答案 0 :(得分:9)
我找到了答案和解决方法。
基于此article和这个惊人的相关article,使用Class.forName(className, true, classLoader)
是一个坏习惯,因为它会使类无限期地缓存在内存中。
解决方案是使用classLoader.loadClass(clasName)
代替,然后完成后,取消引用classLoader
并使用以下方法调用垃圾收集器:
classLoader = null;
System.gc();
希望这有助于他人! :)
背景信息:
我的项目很复杂:我们有一台GWT服务器充当另一台服务器的RMI客户端。因此,要创建实例,GWT需要从服务器下载类并加载它们。稍后,GWT会将实例重新发送到服务器,以使用Hibernate将它们保存在数据库中。为了支持热部署,我们选择动态类加载,用户上传jar并通知服务器谁将从中加载类并将它们呈现给GWT服务器
答案 1 :(得分:3)
在Java 7 URLClassLoader中有一个#close()
方法可以修复此问题。