Java类装入器何时以及如何被标记为垃圾回收?

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

更新类路径并触发热部署后,我们进行了堆转储。堆转储(使用内存分析器)指示旧的类装入器未被垃圾回收。父类装入器中的某些类正在缓存旧的类装入器。调用了以下各项来清除这些缓存:

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

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

  • 类装入器装入的类
  • java.lang.Package 是由类装入器本身创建的
  • java.lang.Protection由类装入器本身创建的域

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


答案 1

我总是听说卸货是有问题的。从理论上讲,当没有引用对象实例并且不需要类卸载时,它们会被垃圾回收,但在实践中似乎更有问题。细微的引用可能会泄漏并阻止回收。在应用程序服务器中,经过多次重新部署周期后,我有时会得到一个.ClassloaderClassloaderOutOfMemoryError: PermGen space

总而言之,我想在某个地方有一个令人讨厌的引用阻止它被收集 - 也许内存分析器没有正确跟踪链接。似乎所有这些都可能发生,如以下文章所述:

另外,我不知道你到底在做什么,但是如果你能等到JDK 7,你可以看看。将介绍它们以更好地支持动态语言,如本文所述:AnonymousClassLoader

我希望它能帮助你。


答案 2

推荐