我在 Tomcat 6.0.35 服务器中的两个应用程序中出现内存泄漏,这些应用程序“突然出现”。一个应用程序是 Solr,另一个是我们自己的软件。我希望有人以前见过这种情况,因为过去几周我一直在发生这种情况,我必须在生产环境中不断重启 Tomcat。
尽管没有触及任何与线程或数据库连接操作相关的代码,但它出现在我们的原始服务器上。由于运行此应用程序的旧服务器即将退役,因此我将站点迁移到新服务器和“更清洁”的环境,其想法是清除任何遗留内容。但它继续发生。
就在 Tomcat 关闭之前,catalina.out 日志充满了如下错误:
2012-04-25 21:46:00,300 [main] 错误 org.apache.catalina.loader.WebappClassLoader- Web 应用程序 [/AppName] 似乎已经启动了一个名为 [MultiThreadedHttpConnectionManager cleanup] 的线程,但未能阻止它。这很可能造成内存泄漏。
2012-04-25 21:46:00,339 [main] 错误 org.apache.catalina.loader.WebappClassLoader-Web 应用程序 [/AppName] 似乎已经启动了一个名为 [com.mchan ge.v2.async.ThreadPoolAsynchronousRunner$ 的线程PoolThread-#2] 但未能阻止它。这很可能造成内存泄漏。
2012-04-25 21:46:00,470 [main] 错误 org.apache.catalina.loader.WebappClassLoader-Web 应用程序 [/AppName] 仍在处理尚未完成的请求。这很可能造成内存泄漏。您可以使用标准上下文实现的 unloadDelay 属性来控制请求完成的时间。
在迁移期间,我们从 Solr 1.4->Solr 3.6 尝试解决问题。当上面的错误开始填充日志时,下面的 Solr 错误紧随其后,重复了 10-15 次,然后 tomcat 停止工作,我必须关闭并启动才能让它响应。
2012-04-25 21:46:00,527 [main] 错误 org.apache.catalina.loader.WebappClassLoader-Web 应用程序 [/solr] 创建了一个 ThreadLocal,其键类型为 [org.a pache.solr.schema.DateField。 ThreadLocalDateFormat](值 [org.apache.solr.schema.DateField$ThreadLocalDateFormat@1f1e90ac])和类型 [org.apache.solr. schema.DateField.ISO8601CanonicalDateFormat] (值 [org.apache.solr.schema.DateField$ISO8601CanonicalDateFormat@6b2ed43a])但在 web 应用程序停止时无法将其删除。这很可能造成内存泄漏。
我的研究提出了很多关于更改管理线程的代码以确保它们杀死数据库池连接等的建议,但该代码在近 12 个月内没有更改。Solr 应用程序也崩溃了,这是第 3 方,所以我的想法是这是环境问题(jar 冲突、版本控制、配置胖手指?)
我的最后一个更改是将用于 java 的 mysql 连接器更新到最新版本,因为在早期版本中池中存在一些内存泄漏错误,但服务器仅在几个小时后再次崩溃。
我刚刚注意到的一件事是我在 Tomcat Web 管理器中看到了数千个会话,但这可能是一个红鲱鱼。
如果有人看到这个,任何帮助都非常感谢。
[编辑]
我想我找到了问题的根源。毕竟这不是内存泄漏。我已经从另一个开发团队接管了一个应用程序,该团队使用c3p0通过 Hibernate 进行数据库池。c3p0 有一个错误/功能,如果您不释放数据库连接,一旦使用了所有连接(通过 MaxPoolSize:默认为 15),c3p0 可以进入等待状态。它将无限期地等待连接可用。因此我的摊位。
我首先将 MaxPoolSize 从 25->100 提高,我的应用程序运行了几天而没有挂起,然后从 100->1000 开始,从那以后它一直稳定运行(超过 2 周)。
这不是完整的解决方案,因为我需要找出它耗尽池连接的原因,因此我还将 c3p0 的 unreturnedConnectionTimeout 设置为 4 小时,这对所有连接强制执行 4 小时的时间限制,无论它们是否处于活动状态。如果它是一个活动连接,它将关闭它并重新打开。
不漂亮,c3p0 不推荐它,但它给了我一些喘息的空间来找出问题的根源。
注意:当 c3p0 与 Hibernate 一起使用时,设置存储在您的 persistence.xml 文件中,但并非所有设置都可以放在那里。某些设置(例如 unreturnedConnectionTimeout)必须进入c3p0.properties