gpt4 book ai didi

java - Guice 3.0 + Tomcat 7.0 = ClassLoader 内存泄漏

转载 作者:搜寻专家 更新时间:2023-10-30 21:30:07 24 4
gpt4 key购买 nike

我知道这个问题已经存在了至少 3 年 ( Issue 92 ),但我仍然对它的当前状态不满意。我也知道,如果您在重新部署后重新启动,这不会影响 Tomcat(如 Guice + Tomcat potential memory leak 中所建议)。

我的问题是在一些重新部署后我遇到了 OutOfMemoryError: PermGen 错误。请注意,我没有明确使用 google-collections,我只使用 Guice 3.0(通过 maven)。分析堆转储后,我仍然看到线程 com.google.inject.internal.Finalizer 仍然处于 Activity 状态,保留对 Tomcat 的 WebappClassLoader 的引用,从而阻碍了垃圾收集。

如果我实际上需要重新部署而不重新启动并且正在使用 Guice 怎么办?我有哪些选择?

最佳答案

嗯,没有人在那里帮助我,所以这是我学到的:

Finalizer 线程由 FinalizableReferenceQueue (FRQ) 启动。在 MapMaker 中存在对 FRQ 的硬(静态)引用。 WebAppClassLoader 没有被垃圾回收,因为 MapMaper 由于硬引用而仍然存在。

以下代码解决了我的问题:

final Class<?> queueHolderClass = 
Class.forName("com.google.inject.internal.util.$MapMaker$QueueHolder");
final Field queueField = queueHolderClass.getDeclaredField("queue");
// make MapMaker.QueueHolder.queue accessible
queueField.setAccessible(true);
// remove the final modifier from MapMaker.QueueHolder.queue
final Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(queueField, queueField.getModifiers() & ~Modifier.FINAL);
// set it to null
queueField.set(null, null);

这是有问题的代码(com.google.inject.internal.util.MapMaker):

/** Wrapper class ensures that queue isn't created until it's used. */
private static class QueueHolder {
static final FinalizableReferenceQueue queue = new FinalizableReferenceQueue();
}

完成此操作后,Finalizer 线程优雅地结束。

关于java - Guice 3.0 + Tomcat 7.0 = ClassLoader 内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8842256/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com