何时以及如何将java类加载器标记为垃圾收集?

时间:2010-02-26 21:32:05

标签: java garbage-collection classloader memory-leaks

我们正在创建多个子类加载器,以将多个子应用程序加载到Java应用程序“容器”中,进行热部署原型设计。当特定类加载器的类路径发生更改(即已添加,删除,更新了jar)时,旧的类加载器将被丢弃(未引用),并为新的jar类路径创建新的类加载器。

更新类路径后,触发热部署,我们进行了堆转储。堆转储(使用Memory Analyzer)表明旧的类加载器没有被垃圾回收。父类加载器中的某些类正在缓存旧的类加载器。调用以下内容来清除这些缓存:

java.lang.ResourceBundle.clearCache(classLoader);
org.apache.commons.logging.LogFactory.release(classLoader);
java.beans.Introspector.flushCaches();

即使在清除了上述缓存之后,旧的类加载器仍然没有被垃圾收集。对类加载器的其余引用包括以下内容:

  • classloader加载的类
  • java.lang.Package由类加载器本身创建
  • 由类加载器本身创建的java.lang.ProtectionDomain

以上所有都是类加载器中的循环引用,它应该触发垃圾回收。我不确定为什么不是。有没有人知道为什么即使使用循环引用,旧的类加载器仍然没有被垃圾收集?

1 个答案:

答案 0 :(得分:17)

我总是听说Classloader卸货有问题。当没有引用对象实例并且没有必要卸载类时,它们被theoretically垃圾收集,但实际上它似乎更有问题。微妙的引用可能会泄漏并阻止Classloader被回收。在应用程序服务器中,经过多次重新部署循环后,我有时会得到OutOfMemoryError: PermGen space

所有这一切,我想有一个令人讨厌的参考,以防止它被收集 - 也许内存分析器没有正确地遵循链接。似乎所有这一切都可能发生,如这些文章所述:

另外,我不确切知道你在做什么,但是如果你可以等到JDK 7,你可以看一下AnonymousClassLoader。它们将被引入以更好地支持动态语言,如本文所述:

我希望它会对你有所帮助。