2012-04-02 55 views
31

我有一個Tomcat 7在Linux上運行,我通過$CATALINA_HOME/bin/shutdown.sh
通過$CATALINA_HOME/bin/startup.sh和關機開始從/etc/init.dTomcat不停止。我怎樣才能調試呢?

一切正常,除了1點的問題。有時tomcat不會停止。
雖然我停下來,我看到在catalina.out日誌中正在下降,如果我ps -ef我仍然可以看到進程運行。

可能是什麼問題?我怎樣才能調試呢?我的感覺是,這與線程有關。

讓可疑的部分如下:
1)我用Log4j的日誌管理,以檢測是否log4j的配置已經改變,但我Log4jManager.shutdown上一個contextDestroyedServletContextListener
2)我用H2數據庫和我看到關機:

重度:Web應用程序[/爲MyApplication]似乎已經啓動名爲[H2日誌寫入所有MyApplication]一個
線程,但未能阻止它。
這很可能造成泄漏

嚴重記憶:Web應用程序[/爲MyApplication]似乎已經開始了
線程名爲[H2文件鎖定看門狗
的/ opt/MYORG/tomcat的/ webapps /下所有MyApplication /db/myDatabase.lock.db]但有
無法停止它。這很可能造成內存泄漏。 4月2日,
2012上午09時08分08秒org.apache.catalina.loader.WebappClassLoader
clearReferencesThreads重度:Web應用程序[/爲MyApplication]
似乎已經開始了一個名爲[FileWatchdog]線程,但未能
停止它。這很可能造成內存泄漏。

請幫忙嗎?我如何在這裏檢測到問題?

UPDATE:
我做了kill -3通過@daveb的建議,並在catalina.out的我看到:

JVMDUMP006I處理傾倒事件 「用戶」,細節 「」 - 請稍候。 JVMDUMP032I JVM使用要求 「/etc/init.d/javacore.20120402.093922.2568.0001.txt」 Java轉儲響應寫入 /etc/init.d/javacore.20120402.093922.2568.0001.txt的 事件JVMDUMP010I Java轉儲JVMDUMP013I 已處理的轉儲事件「user」,詳細信息「」。

/etc/init.d有一個javacore,但我不知道如何處理它。即我應該調查哪些部分

+0

嘗試將您的線程標記爲守護線程,以便虛擬機不會等待它們死亡。 http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#setDaemon(boolean)但是,當然這隻對你自己的線程有用,而不是H2 – luukes 2012-04-02 06:53:53

+0

H2開始的創建守護線程。 – 2012-04-02 09:54:19

+0

@ThomasMueller:那麼'SEVERE:Web應用程序[/ MYAPPLICATION]看起來是否啓動了一個名爲[H2 File Lock Watchdog /opt/myOrg/tomcat/webapps/MyApplication/lock.db]的線程,但未能停止它。這很可能會造成內存泄漏.'意味着在catalina.out?我沒有創建這個,但是'H2'。 – Jim 2012-04-02 11:09:54

回答

4

如果Web應用程序已停止,則應關閉與數據庫的所有連接。如果您沒有連接列表,則執行SQL語句「shutdown」(這僅適用於H2和HSQLDB數據庫)。

如果你已經註冊了一個Servlet,你可以在Servlet.destroy()方法中做到這一點。

如果您註冊了ServletContextListener,則可以執行ServletContextListener.contextDestroyed(ServletContextEvent servletContextEvent)方法中的「關閉」語句。這就是org.h2.server.web.DbStarterServletContextListener所做的(包含在H2數據庫中的)。

+0

感謝您的回覆!'如果Web應用程序停止,所有與數據庫的連接也應該關閉。我正在使用Tomcat的連接池。所以它已經不在我的手中了。這是Tomcat和H2之間的一個衆所周知的'賽跑'問題。我可以做'SHUTDOWN'(它安全嗎?),但我想確保我正確解決這個問題 – Jim 2012-04-02 12:55:46

+0

它看到了問題。不知道最好的解決方案是什麼...忽略異常? 「SHUTDOWN」語句只會關閉這個數據庫,所以應該相對保存 - 只有當您不確定其他Web應用程序是否正在使用該數據庫時,纔會這樣做。另一種解決方案是使用服務器模式(在另一個進程中運行H2數據庫)。 – 2012-04-02 13:40:06

+0

:沒有數據庫是我的,即沒有其他應用程序將訪問它。而我需要在文件模式下使用它。所以基本上你是說1)關機對於數據是安全的2)我可以忽略這個異常,意思是什麼?由於H2還在運行,Tomcat不會在關機時掛起?我在我的應用程序目錄中看到'db.lock'文件 – Jim 2012-04-02 13:49:34

19

找出什麼的線程仍在運行(或阻塞,等待運行)通過使用jstack或將信號發送到進程:

kill -3 pid 

當你知道這一點,你可以無論是開始他們掛鉤到關閉通知停止線程。或者讓這些線程deamon線程。

有關詳細信息,請參見This tomcat shutdown question

如果你不知道你的線程是在哪裏創建的,那麼考慮給它們添加名字 - executors可以帶線程工廠,並且你可以使用這些工廠來設置線程的deamon狀態並且命名它 - 你的堆棧跟蹤會更清晰。

+0

+1。請參閱OP – Jim 2012-04-02 07:03:21

+0

中的更新在文本編輯器中打開javacore .txt文件,查找包含您編寫的軟件包的線程堆棧。 – daveb 2012-04-02 07:09:44

+0

是的,我想通了,但我不知道什麼表明一個錯誤。 – Jim 2012-04-02 07:16:02

6

我有完全相同的問題。有時候,命令./shutdown.sh不會停止tomcat進程,其進程java停留在正在運行的進程中。

我已經使用了Ubuntu軟件倉庫的Tomcat的版本,要解決這個問題:

sudo apt-get install tomcat7 

從包管理器安裝並配置一些設置後,我並沒有對停止/啓動Tomcat任何問題。我用這個命令停止的,它從不失敗:

service tomcat7 stop 

這是幾乎相同

/etc/init.d/tomcat7 stop 

使用此命令,從init腳本運行的代碼塊,具體而言,代碼從文件/etc/init.d/tomcat7。所以我研究了它,看看它總是殺死tomcat進程成功。下面是當您使用service tomcat7 stop命令運行該代碼塊:

log_daemon_msg "Stopping $DESC" "$NAME" 

     set +e 
     if [ -f "$CATALINA_PID" ]; then 
       start-stop-daemon --stop --pidfile "$CATALINA_PID" \ 
         --user "$TOMCAT7_USER" \ 
         --retry=TERM/20/KILL/5 >/dev/null 
       if [ $? -eq 1 ]; then 
         log_progress_msg "$DESC is not running but pid file exists, cleaning up" 
       elif [ $? -eq 3 ]; then 
         PID="`cat $CATALINA_PID`" 
         log_failure_msg "Failed to stop $NAME (pid $PID)" 
         exit 1 
       fi 
       rm -f "$CATALINA_PID" 
       rm -rf "$JVM_TMP" 
     else 
       log_progress_msg "(not running)" 
     fi 
     log_end_msg 0 
     set -e 
     ;; 

最重要的部分是這樣的:

start-stop-daemon --stop --pidfile "$CATALINA_PID" \ 
          --user "$TOMCAT7_USER" \ 
          --retry=TERM/20/KILL/5 >/dev/null 

這意味着「直到進程停止重試停止。下面是從起止守護手冊--retry命令文檔:

-R|--retry timeout|schedule 
      With --stop, specifies that start-stop-daemon is to check 
      whether the process(es) do finish. It will check repeatedly 
      whether any matching processes are running, until none are. If 
      the processes do not exit it will then take further action as 
      determined by the schedule. 

      If timeout is specified instead of schedule then the schedule 
      signal/timeout/KILL/timeout is used, where signal is the signal 
      specified with --signal. 
      ... 

所以,--retry=TERM/20/KILL/5意味着「發送TERM信號的過程中,等待20秒,如果它仍然運行,發送KILL信號,等待5秒鐘,如果還在運行,出現問題

這意味着你可以配置tomcat作爲deamon運行並使用類似這樣的命令,或者寫入一個腳本來做這種動作來阻止tomcat,或者只是使用Ubuntu並從包管理器中獲取tomcat。

7

檢查您的Web應用程序是否有一些調度程序處於活動狀態,如Quartz。

如果你不阻止它,Web應用程序線程上房,直到你殺了它

1

在我來說,我有一個流氓的JPA EntityManager,這是使用後沒有被正確關閉。修正了,現在我可以再次清理並重新構建,而不必每次都殺死該死的Java進程:)

0

我也有同樣的問題。我的應用程序中沒有關機的ThrottledThreadPoolExecutor。當我正確關閉它時,tomcat會乾淨地停下來。爲了找出問題,我必須從我的tomcat webapps目錄中刪除所有應用程序,然後逐個添加它們,並查看哪一個導致了問題

0

如果您使用的是調度程序或其他實體在你的網絡應用程序中,你需要關閉它。通常,您必須使用ServletContextListener來提供掛鉤以進行關閉調用。在這種情況下,關閉鉤子不起作用,因爲JVM尚未關閉(尚)。相信我,我已經嘗試過了。如果你的代碼是在代理代碼或者容器/ web應用程序之外的,那麼關閉鉤子應該可以工作,儘管通常是找出爲什麼它仍然不工作的原因。請注意,我是禿頭的。

相關問題