2011-12-30 77 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泄漏的其他文章。