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

标签 java garbage-collection classloader memory-leaks

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

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

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

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

  • 类加载器加载的类
  • java.lang.Package 由类加载器自己创建
  • 类加载器自己创建的java.lang.ProtectionDomain

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

最佳答案

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

所有这一切都是说我猜某处有一个讨厌的引用阻止它被收集——也许内存分析器没有正确地跟踪链接。正如这些文章中所述,这一切似乎都可能发生:

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

希望对你有帮助。

关于java - 何时以及如何将 java 类加载器标记为垃圾收集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2344964/

相关文章:

java - 如何在1个Java类中加载同一个Jar的2个版本

java - 公式操作算法

Java 记录和字段注释

java - JFreeCharts TimeSeriesCharts 没有 X 值

c++ - 什么时候需要在 Ruby C 扩展中声明 volatile VALUE?

java.nio.ByteBuffer - allocateDirect 和垃圾收集

java - 使用Reflections动态加载包中的所有类

java - 多树和优先排序算法

javascript - ES6 const 会影响垃圾回收吗?

不应该运行的代码上的 PHP 错误