Tomcat不会停止.我该怎么调试呢?

Jim*_*Jim 32 java linux multithreading tomcat h2

我有一个Tomcat 7在Linux上运行,我通过开始$CATALINA_HOME/bin/startup.sh通过和关闭$CATALINA_HOME/bin/shutdown.sh
/etc/init.d

一切都没问题,除了1个问题.有时tomcat不会停止.
虽然我停止它,但我看到catalina.out日志正在下降,如果我这样做,ps -ef我仍然可以看到进程正在运行.

可能是什么问题呢?我该怎么调试呢?我的感觉是,这与线程有关.

因此,可疑的部分如下:
1)我使用Log4j的LogManager来检测log4j配置是否已经更改,但我做Log4jManager.shutdowncontextDestroyed ServletContextListener
2)我使用H2数据库,我在关机时看到:

严重:Web应用程序[/ MyApplication]似乎已经启动了一个
名为[H2 Log Writer MYAPPLICATION] 的线程,但未能阻止它.
这很可能造成内存泄漏

严重:Web应用程序[/ MyApplication]似乎已经启动了一个
名为[H2 File Lock Watchdog
/opt/myOrg/tomcat/webapps/MyApplication/db/myDatabase.lock.db] 的线程,但
未能阻止它.这很可能造成内存泄漏.
2012年4月2 日上午9:08:08 org.apache.catalina.loader.WebappClassLoader
clearReferencesThreads严重:Web应用程序[/ MyApplication]
似乎已经启动了一个名为[FileWatchdog]但未能
阻止它的线程.这很可能造成内存泄漏.

有什么帮助吗?我怎样才能在这里发现问题?

更新:
kill -3按照@daveb的建议做了一个,并在catalina.out中看到:

JVMDUMP006I正在处理转储事件"user",详细信息"" - 请稍候.JVMDUMP032I JVM使用'/etc/init.d/javacore.20120402.093922.2568.0001.txt'请求Java转储,以响应写入/etc/init.d/javacore.20120402.093922.2568.0001.txt的JVMDUMP010I Java转储事件JVMDUMP013I已处理的转储事件"用户",详细信息"".

有一个javacore /etc/init.d但我不知道如何处理它.即我应该调查哪些部分

dav*_*veb 19

通过使用jstack或向进程发送信号,找出仍在运行(或阻塞,等待运行)的线程:

kill -3 pid
Run Code Online (Sandbox Code Playgroud)

当你知道这一点时,你可以做任何开始它们挂钩到关闭通知以停止线程.或者让那些线程成为deamon线程.

有关详细信息,请参阅此tomcat关闭问题.

如果你不知道你的线程在哪里创建,那么考虑为它们添加名称 - 执行者可以使用线程工厂,你可以使用这些工厂来设置线程的deamon状态并命名它 - 所以你的堆栈跟踪将更清楚.


Utk*_*mir 7

我有同样的问题.有时,该命令./shutdown.sh不会停止tomcat进程,并且其java进程将保留在正在运行的进程中.

我使用Ubuntu软件存储库中的Tomcat版本解决了这个问题,方法是:

sudo apt-get install tomcat7
Run Code Online (Sandbox Code Playgroud)

从包管理器安装并配置一些设置后,我在停止/启动Tomcat时没有任何问题.我使用此命令停止,它从未失败:

service tomcat7 stop
Run Code Online (Sandbox Code Playgroud)

这几乎是一样的

/etc/init.d/tomcat7 stop
Run Code Online (Sandbox Code Playgroud)

使用此命令从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
        ;;
Run Code Online (Sandbox Code Playgroud)

重要的是这个:

start-stop-daemon --stop --pidfile "$CATALINA_PID" \
                            --user "$TOMCAT7_USER" \
                            --retry=TERM/20/KILL/5 >/dev/null
Run Code Online (Sandbox Code Playgroud)

这意味着"重试停止直到进程停止.这是来自start-stop-daemon手册的--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.
          ...
Run Code Online (Sandbox Code Playgroud)

因此,--retry=TERM/20/KILL/5意味着" 向过程发送TERM信号,等待20秒,如果它仍在运行,发送KILL信号,等待5秒,如果它仍在运行,则存在问题.

这意味着你可以配置tomcat作为deamon运行并使用这样的命令,或编写脚本来执行这种操作来停止tomcat,或者只是使用Ubuntu并从包管理器获取tomcat.


小智 7

检查您的Web应用程序是否有一些活动的调度程序,如Quartz.

如果你不停止它,Web应用程序线程永远不会结束,直到你杀死它


Tho*_*ler 4

如果 Web 应用程序停止,则所有与数据库的连接也应关闭。如果没有连接列表,则执行 SQL 语句“shutdown”(这只适用于 H2 和 HSQLDB 数据库)。

如果您已经注册了 Servlet,则可以在该Servlet.destroy()方法中执行此操作。

如果您已经注册了ServletContextListener,则可以在方法中执行“shutdown”语句ServletContextListener.contextDestroyed(ServletContextEvent servletContextEvent)。这就是org.h2.server.web.DbStarter ServletContextListener(H2 数据库中包含的)的作用。