2011-12-30 54 views
3

我仍然在tomcat/logs/catalina.out中看到此错误。Catalina.out内存泄漏错误

Dec 29, 2011 4:04:36 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads 
SEVERE: The web application [/LoggingMonitor] appears to have started a thread named [Timer-1] but has failed to stop it. This is very likely to create a memory leak. 
Dec 29, 2011 4:04:36 PM org.apache.coyote.http11.Http11Protocol destroy 
INFO: Stopping Coyote HTTP/1.1 on http-8180 

是否值得考虑,如果是,我该如何纠正?

回答

3

这可能是没什么大不了的(只是杀-9或东西),并很容易修复。只要找出哪些Web应用程序在的上下文中运行/ LoggingMonitor然后用grep其代码库...

new Timer(); 

...,并与全部更换...

new Timer(true); 

java.util中。默认情况下,Timer不会在守护进程线程中运行。您需要webapps中的任何Timers在守护进程线程上运行(否则容器无法正常关闭,因为它正在等待Timer线程结束,而永远不会这样做)。找到所有“新的Timer()”调用并将其替换为“新的Timer(true)”,并且记录投诉应该停止。

花JavaDoc中一些时间学习一些关于守护与非守护线程:http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Timer.html

当我的webapps我工作,我一直当我最终会做任何我自己的多线程的使用守护线程。随着java.util.concurrent中的设施,这变得非常罕见(不得不做我自己的线程的东西)。

最后,为了记录,我讨厌java.util.Timer并始终推荐使用ScheduledExecutor之类的工具来执行定期的重复性任务。它很容易在定时器中搞砸,并取出它执行的Tread,守护进程或其他。

+0

其实我正在做的是监视一个正在不断更新的日志文件,我在每秒钟后运行的计时器的帮助下做到这一点。可以建议一些更好的技术,将不胜感激, – Rookie 2012-01-02 11:25:06

+1

警告消息似乎来自服务器仍在运行时。可能只是重新启动一个webapp。守护进程属性不会解决这个问题。它应该彻底退出关闭servlet上下文事件。 – 2012-01-02 14:18:39

2

这消息是不是一个大问题,如果永远停止Tomcat,如果取消部署/重新部署应用,否则这些操作会导致内存泄漏什么大不了的事,expecially生产。

Bob Kuhar建议的java.util.Timer(也可能是其他类)创建了名为“Timer-#”的线程,但是擦除自己的代码库可能不够,并且确保使用守护程序线程并不会消除该消息(Tom Hawtin的评论是正确的)。

当我使用一个守护线程消息它是由我的代码传递依赖产生,正是由Apache的共享池V1.3的GenericObjectPool类(见source code)。为了找到实例化Timer的类,我必须在每个Timer类的构造函数中放入一个断点,然后检查调用堆栈。为了解决这个问题,我不得不升级库(较新版本的Commons Pool不使用该Timer)。

当您控制实例化线程的代码时,您可以通过确保在应用程序停止时停止线程来解决问题。使用守护进程线程是一种很好的做法,但这还不够,因为守护线程只有在关闭Tomcat时才会自动死掉,而不是在您取消部署应用程序时自动死掉。

在更普遍的情况下,当您不知道谁创建了讨厌的线程时,请检查Finding Source of Thread Creation in a Java applicationDetect Who Created a Thread (w. Eclipse)

UPDATE

完全不同的方法是使用非常有趣Leak Prevention Listener。还请阅读该作者关于classloader泄漏的其他文章。