Guice + Tomcat 潜在的内存泄漏问题

12

我刚开始在我的Tomcat webapp中使用Google Guice,每当WAR文件未部署时,我会在catalina.out文件中看到以下内容:

May 16, 2011 5:37:24 PM org.apache.catalina.startup.HostConfig checkResources INFO: 正在取消部署上下文[/app]

May 16, 2011 5:37:24 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads SEVERE: 一个Web应用程序似乎已经启动了一个名为[com.google.inject.internal.util.$Finalizer]的线程,但未能停止它。这很可能会导致内存泄漏。

May 16, 2011 5:37:24 PM org.apache.catalina.loader.WebappClassLoader clearThreadLocalMap SEVERE: 一个Web应用程序创建了一个ThreadLocal,其键类型为[null](值为[com.google.inject.internal.InjectorImpl$1@10ace8d]),值类型为[java.lang.Object[]](值为[[Ljava.lang.Object;@7e9bed]),但在Web应用程序停止时未能将其删除。为防止内存泄漏,ThreadLocal已被强制删除。

有人知道是什么原因引起的吗?或者我该如何阻止它发生?

我只是按照这里的说明进行操作http://code.google.com/docreader/#p=google-guice&s=google-guice&t=ServletModule,尚未进行任何高级操作。我只有两个servlet和一个过滤器。

谢谢!

3个回答

5

3
如果您在关闭Web应用程序时遇到此问题,我不会太担心。这种资源泄漏在应用程序关闭时很常见。当您频繁进行热部署(即在不杀死JVM的情况下多次取消部署)时,它们会成为问题,但是当执行冷部署时(在重新部署之前杀死JVM时执行取消部署/部署),它们不会成为问题。
一种常见策略是在开发过程中进行热部署(因为它们通常比冷部署更快),并且只有在资源泄漏开始影响性能时才进行冷部署。然后,在生产环境中,每次部署都要进行冷部署。考虑到具有此类泄漏的代码/库的数量,尝试消除它们可能会很难。

2
我同意这可能是无需担心的,但我喜欢我的日志保持干净。我已经将此发布为问题630:http://code.google.com/p/google-guice/issues/detail?id=630。 - Peter Sankauskas
2
重新部署 Web 应用程序是一个真实的使用情况,仅为其中一个重启所有 Web 应用程序(JVM)可能会带来真正的运维痛苦。 - Nicolas
1
线程应该在一个JVM中共享,当应用程序再次部署时,Guice不会创建另一个线程。这是怎么做到的呢?这意味着不仅对象(及其类)仍然保留在堆内存(和permgen)中,而且还意味着Guice使用由另一个类加载器定义的类定义的对象,因为它无法看到它们。 - Plap
一种常见的策略是在开发过程中进行热部署[...] 然后,在生产环境中,每次部署都进行冷部署。也许在Tomcat 7之前这可能是正确的,但现在Tomcat 7具有并行部署功能:使用此功能可以避免停机时间,如果不与其他Tomcat实例平衡,则可以处理内存泄漏问题。 - reallynice

0
这帮助我消除了关于com.google.inject.internal.InjectorImpl的“SEVERE”日志条目:
injector = null;
System.gc(); 

其中,injector 是 Guice.createInjector(...modules...) 的结果。

我承认,看起来我没有阅读关于 调用 System.gc() 的坏习惯,但这完全是有道理的,因为 Guice 在内部使用弱引用。

P.S. Tomcat 8,Java 8,Guice 3.0。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接