Tomcat не останавливается. Как я могу отладить это?

У меня есть Tomcat 7 работает в Linux, который я запускаю через $CATALINA_HOME/bin/startup.sh и отключение через $CATALINA_HOME/bin/shutdown.sh
от /etc/init.d

Все в порядке, кроме 1 проблемы. Иногда кот не останавливается.
Хотя я останавливаю это и вижу в логах catalina.out, что идет вниз, если я делаю ps -ef Я все еще вижу, как идет процесс.

В чем может быть проблема? Как я могу отладить это? Мне кажется, что это связано с темами.

Таким образом, подозрительные части следующие:
1) Я использую LogManager Log4j, чтобы определить, была ли изменена конфигурация log4j, но я делаю Log4jManager.shutdown на contextDestroyedServletContextListener
2) пользуюсь H2 База данных и я вижу на отключение:

SEVERE: веб-приложение [/MyApplication], похоже, запустило
поток с именем [H2 Log Writer MYAPPLICATION], но не смог остановить его.
Это очень вероятно, чтобы создать утечку памяти

SEVERE: веб-приложение [/MyApplication], похоже, запустило
поток с именем [H2 File Lock Watchdog
/opt/myOrg/tomcat/webapps/MyApplication/db/myDatabase.lock.db], но имеет
не смог остановить это. Это очень вероятно, чтобы создать утечку памяти. 2 апреля,
2012 9:08:08 org.apache.catalina.loader.WebappClassLoader
clearReferencesThreads SEVERE: веб-приложение [/MyApplication]
кажется, что запустил поток с именем [FileWatchdog], но не удалось
чтобы остановить это. Это очень вероятно, чтобы создать утечку памяти.

Любая помощь, пожалуйста? Как я могу обнаружить проблему здесь?

ОБНОВИТЬ:
Я сделал kill -3 как предложено @daveb, и в catalina.out я вижу:

JVMDUMP006I Обрабатывается событие дампа "пользователь", подробности "" - пожалуйста, подождите. JVMDUMP032I JVM запросила дамп Java с использованием файла /etc/init.d/javacore.20120402.093922.2568.0001.txt в ответ на событие JVMDUMP010I Дамп Java, записанный в /etc/init.d/javacore.20120402.093922.2568.0001.txt событие JVMDML0101 "пользователь", деталь "".

В Хавок есть /etc/init.d но я не знаю, как это обработать. Т.е. какие части я должен исследовать

7 ответов

Решение

Если веб-приложение остановлено, все подключения к базе данных также должны быть закрыты. Если у вас нет списка подключений, выполните оператор SQL "shutdown" (это работает только для баз данных H2 и HSQLDB).

Если у вас есть зарегистрированный сервлет, вы можете сделать это в Servlet.destroy() метод.

Если вы зарегистрировали ServletContextListener, вы можете выполнить инструкцию "shutdown" в ServletContextListener.contextDestroyed(ServletContextEvent servletContextEvent) метод. Это то, что org.h2.server.web.DbStarterServletContextListener делает (тот, который включен в базу данных H2).

Узнайте, какие потоки все еще работают (или заблокированы, ожидая запуска), используя jstack или отправив сигнал процессу:

kill -3 pid

Когда вы это знаете, вы можете сделать все, что бы они ни начали, подключить их к уведомлению о завершении работы, чтобы остановить потоки. Или сделай эти темы темными.

Посмотрите Этот вопрос о выключении tomcat для более подробной информации об этом.

Если вы не знаете, где были созданы ваши потоки, подумайте о том, чтобы добавить к ним имена - исполнители могут использовать фабрики потоков, и вы можете использовать эти фабрики, чтобы установить статус deamon потока, а также присвоить ему имя - так что трассировка стека будет быть яснее

Проверьте, есть ли в вашем веб-приложении активный планировщик, например, Quartz.

Если вы не остановите это, поток веб-приложений никогда не прекратится, пока вы его не убьете

У меня была точно такая же проблема. Иногда команда ./shutdown.sh не останавливает процесс кота, а его java процесс остается в запущенных процессах.

Я решил эту проблему, используя версию Tomcat в репозиториях программного обеспечения Ubuntu:

sudo apt-get install tomcat7

После установки из диспетчера пакетов и настройки некоторых параметров у меня не возникло проблем при остановке / запуске Tomcat. Я использовал эту команду для остановки, и она никогда не подводила:

service tomcat7 stop

что почти так же, как

/etc/init.d/tomcat7 stop

С помощью этой команды запускается блок кода из сценария инициализации, в частности, коды из файла /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 из руководства start-stop-daemon:

   -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 для запуска в качестве демона и использовать подобную команду, или написать сценарий для выполнения такого действия, чтобы остановить tomcat, или просто использовать Ubuntu и получить tomcat из диспетчера пакетов.

У меня тоже была такая же проблема. В моем приложении был ThrottledThreadPoolExecutor, который не отключался. Когда я выключу его правильно, кот полностью остановится. Чтобы выяснить проблему, мне пришлось удалить все приложения из моего кота webapps каталог, а затем добавить их по одному и посмотреть, какой из них вызывает проблему

Если вы используете Планировщик или какой-либо другой объект в своем веб-приложении, вам необходимо отключить его. Как правило, вы должны использовать ServletContextListener, чтобы обеспечить ловушку для выполнения вызова выключения. В этом случае хук отключения не будет работать, потому что JVM не выключается (пока). Поверьте мне, я пытался. Если ваш код находится в коде агента или что-то за пределами контейнера / веб-приложения, то СЛЕДУЕТ работать хук выключения, хотя часто бывает сложно потрудиться выяснить, почему он ПО-прежнему не работает. Обратите внимание, я лысый.

В моем случае у меня был один мошеннический JPA EntityManager, который не был должным образом закрыт после использования. Исправлено, и теперь я могу снова чистить и строить, не убивая проклятый процесс Java каждый раз:)

Другие вопросы по тегам