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
на contextDestroyed
ServletContextListener
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.DbStarter
ServletContextListener
делает (тот, который включен в базу данных 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 каждый раз:)