Tomcat ne s'arrête pas. Comment puis-je debug?
j'ai un Tomcat 7
tournant sous Linux que je démarre via $CATALINA_HOME/bin/startup.sh
et l'arrêt via $CATALINA_HOME/bin/shutdown.sh
de /etc/init.d
tout va bien sauf un problème. Parfois, tomcat ne s'arrête pas.
Mais je l'arrête et je vois à catalina.sortir les journaux qui vont vers le bas, si je fais ps -ef
je peux encore voir le processus en cours.
Quel est le problème? Comment puis-je debug? Mon le sentiment est, que cela est lié à des fils.
donc les parties qui sont suspectes sont les suivantes:
1) J'utilise LogManager de Log4j pour détecter si la configuration de log4j a été modifiée, mais je fais Log4jManager.shutdown
sur un contextDestroyed
ServletContextListener
2) j'utilise la base de données H2
et je vois sur shutdown:
sévère: L'application web [/MyApplication] semble avoir commencé une
le fil nommé [H2 Log Writer MYAPPLICATION] mais n'a pas réussi à l'arrêter.
Cela est très susceptible de créer une fuite de mémoiregrave: L'application web [/MyApplication] semble avoir commencé un
thread named [H2 fichier Lock Watchdog
/opt/myOrg/tomcat/webapps/Monapplication/db/mabase.verrouillage.db] mais a
pas réussi à l'arrêter. Ce qui est très susceptible de créer une fuite de mémoire. AVR 2,
2012 9:08: 08 AM org.Apache.Catalina.chargeur.WebappClassLoader
clearreferencess'avère sévère: l'application web [/MyApplication]
semble avoir démarré un thread nommé [FileWatchdog] mais a échoué
pour l'arrêter. Ce qui est très susceptible de créer une fuite de mémoire.
de l'aide s'il vous plaît? Comment Je détecte le problème ici?
mise à jour:
J'ai fait un kill -3
comme suggéré par @daveb, et dans le catalina.je vois:
JVMDUMP006I de Traitement des événements de vidage "utilisateur", détail "" - veuillez patienter. JVM demand Java dump using "/etc / init.d / javacore.20120402.093922.2568.0001.txt", en réponse à une événement jvmdump010i Java dump écrit à / etc / init.d / javacore.20120402.093922.2568.0001.txt JVMDUMP013I Traité de vidage de l'événement "utilisateur", détail "".
il y a un javacore dans /etc/init.d
mais je ne sais pas comment le traiter. I. e. quelles pièces dois-je étudier
7 réponses
si l'application web est arrêtée, toutes les connexions à la base de données doivent être fermées. Si vous n'avez pas de liste de connexions, alors exécutez L'instruction SQL "shutdown" (cela ne fonctionne que pour les bases de données H2 et HSQLDB).
si vous avez un Servlet enregistré, vous pouvez le faire avec la méthode Servlet.destroy()
.
si vous avez enregistré un ServletContextListener
, vous pouvez exécuter l'instruction" shutdown "dans la méthode ServletContextListener.contextDestroyed(ServletContextEvent servletContextEvent)
. C'est ce que org.h2.server.web.DbStarter
ServletContextListener
fait (celui qui est inclus dans la base de données H2).
Découvrez quels threads sont encore en cours d'exécution (ou bloqués, en attente d'exécution) en utilisant jstack ou en envoyant un signal au processus:
kill -3 pid
quand vous savez cela, vous pouvez faire ce que c'était qui les a lancés accrocher dans la notification d'arrêt pour arrêter les threads. Ou faire ces fils de fils deamon.
Voir Ce tomcat arrêt en question pour plus de détails sur cette.
Si vous ne savez pas là où vos threads ont été créés, alors envisagez d'y ajouter des noms - les exécuteurs peuvent prendre des usines de threads, et vous pouvez utiliser ces usines pour définir le statut de "deamon" d'un thread et aussi pour le nommer - de sorte que votre trace de pile sera plus claire.
vérifiez si votre Application Web a un Scheduler actif, comme Quartz.
Si vous n'avez pas l'arrêter, Application Web Fil sans fin jusqu'à ce que vous tuer
j'ai eu exactement le même problème. Parfois, la commande ./shutdown.sh
n'arrête pas le processus tomcat, et son processus java
reste dans les processus en cours.
j'avais résolu ce problème en utilisant la version Tomcat dans les dépôts logiciels D'Ubuntu, par:
sudo apt-get install tomcat7
après l'avoir installé à partir du gestionnaire de paquets et après avoir configuré certains paramètres, Je n'ai eu aucun problème pour arrêter/démarrer Tomcat. J'ai utilisé cette commande pour arrêter, et il n'a jamais manqué:
service tomcat7 stop
qui est presque le même que
/etc/init.d/tomcat7 stop
utilise cette commande pour lancer le bloc de code à partir du script d'initialisation, plus précisément les codes du fichier /etc/init.d/tomcat7
. Donc j'ai regardé dedans pour voir ce qu'il fait pour toujours tuer le processus tomcat avec succès. Voici le bloc de code qui s'exécute lorsque vous utilisez la commande 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
;;
la partie importante est celle-ci:
start-stop-daemon --stop --pidfile "$CATALINA_PID" \
--user "$TOMCAT7_USER" \
--retry=TERM/20/KILL/5 >/dev/null
cela signifie" Essayer de s'arrêter jusqu'à ce que le processus soit arrêté. Voici la documentation de la commande --Rety de start-stop-daemon manuel:
-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. ...
donc, --retry=TERM/20/KILL/5
signifie "envoyer terme signal au processus, attendre 20 secondes, si il est toujours en cours d'exécution, envoyer KILL signal, attendre 5 secondes, si il est toujours en cours d'exécution, il ya un problème.
cela signifie que vous pouvez configurer le tomcat pour qu'il fonctionne comme un deamon et utilise une commande comme celle-ci, ou écrire un script pour faire ce genre d'action pour arrêter tomcat, ou tout simplement utiliser Ubuntu et obtenir le tomcat du gestionnaire de paquets.
dans mon cas, j'avais une entité JPA qui n'était pas correctement fermée après utilisation. Corrigé cela, et maintenant je peux nettoyer-et-construire à nouveau sans tuer le foutu processus Java à chaque fois:)
j'ai aussi eu le même problème. Il y avait un accélérateur de particules dans mon application qui ne s'arrêtait pas. Quand je l'arrêtais correctement, tomcat s'arrêtait proprement. Pour résoudre le problème, j'ai dû supprimer toutes les applications de mon répertoire tomcat webapps
et les ajouter une à une et voir laquelle causait le problème
Si vous utilisez un Planificateur ou d'une autre entité dans votre application web, vous devez l'arrêter. En général, vous devez utiliser un ServletContextListener pour fournir le crochet pour faire votre appel d'arrêt. Un crochet d'arrêt ne fonctionnera pas dans ce cas car la JVM ne s'arrête pas (encore). Croyez-moi, j'ai essayé. Si votre code est dans le code agent ou quelque chose à l'extérieur du conteneur / webapp, alors un crochet d'arrêt devrait fonctionner, bien que souvent c'est une expérience de tirer les cheveux pour comprendre pourquoi il est encore pas de travail. Remarque, je suis chauve.