Bonjour,
j'ai une appli java qui tourne sur le serveur Tomcat 5 et j'ai de temps à autre des OutOfMemory.
Auriez-vous des idées pour résoudre ce problème ou pour identifier l'origine du problème ?
Merci pour votre aide![]()
Bonjour,
j'ai une appli java qui tourne sur le serveur Tomcat 5 et j'ai de temps à autre des OutOfMemory.
Auriez-vous des idées pour résoudre ce problème ou pour identifier l'origine du problème ?
Merci pour votre aide![]()
L'activité de déploiement et de repli (deploy/undeploy) conduit à terme à un java.lang.OutOfMemory : Permgen Space
Il faut savoir qu'il n'y a pas grand chose à faire dans ce cas...
Le bug est profond:
Très grossièrement, si tu utilises dans ton application web des librairies externes qui font du chargement dynamique de classes (CGLIB, hibernate (fatal avec lazy=false), ....) et que tu la repli(undeploy), l'URLClassLoader de tomcat gardera les références sur les objets qui ont été chargés dynamiquement durant l'execution de l'appli ce qui empéche le ramasse-miette de les supprimer.
il y a cependant des palliatifs:
Le premier c'est d'utiliser un profiler et de délibérer manuellement les objets devant l'être.
Le second, mais alors c'est vraiment du bricolage c'est d'augmenter la mémoire allouée au permgen de la JVM de Tomcat en ajoutant -XX:MaxPermSize=256M aux options de démarrage dans catalina.sh .Attention car cela crée des ralentissements, et ca ne fait que reporter le problème.
Le troisième, si vous utilisez Tomcat en production, il est indispensable de repérer les applications qui bougent (beaucoup de cycles deploy/undeploy) et des les isoler dans une seconde instance de Tomcat dite "de test"... (c'est une politique genre debian) car il est possible de monter sur une même machine deux tomcat associées à deux JVM indépendantes, cela se fait en manipulant entre autre la variable CATALINA_BASE (et non pas CATALINA_HOME) si tu es sous Linux...
En dehors de tout ceci, certaines librairies tel que la CGLIB comportent des fuites de mémoires reconnues, c'est pour ces raisons que des framework comme Spring ou Hibernate ont rendu l'utilisation de la CGLIB optionnel. (à noter qu'hibernate à eu du mal à rompre ses dépendances envers la CGLIB)
Des outils comme jconsole sont assez utiles pour garder un oeil sur l'incrémentation du permgen jusqu'a ce qu'il atteigne sa valeur critique, et ça permet de mettre le doigt sur le problème (sans le résoudre)...
Essaye de faire tourner ton appli avec d'autres conteneurs de servlets, pour voir si le problème persiste...
bon courage...
Merci pour ta super réponse ! Bonne journée![]()
Bonjour,
Est ce que tu pourrais être plus précis concernant l'utilisation de CATALINA_HOME stp
On m'a demandé dernièrement comment faire pour utiliser un Tomcat, avec deux applis ou chaque appli s'execute dans une JVM indépendante ?Envoyé par TonioLeRital
Est ce que c'est possible ? Ou est ce qu'il faut deux tomcat ?
Bonjour,
Avant toutes choses, sous quel OS es-tu car je l'ai déja fait sous Linux (debian et fedora), mais jamais sous windows.Envoyé par a_defanti
Oui l'OS est Linux.
Par contre suite à la demande qui m'a été faite, je ne sais pas quelle est la différence entre :
_utiliser un Tomcat, avec deux applis ou chaque appli s'execute dans une JVM indépendante
_utiliser deux tomcat avec chacun une appli
Salut,
Tomcat étant un conteneur d'applications dont la gestion des applications est géree par le mécanisme de chargement dynamique de classes (c'est le principe des plugins qui apportent des fonctionnalités supplémentaires à une application sans la redemarrer), on perdrait donc l'intérêt d'utiliser ce genre de conteneurs si les applications hebergées lancaient des processus (JVM) indépendants.Envoyé par a_defanti
Donc configurer 2 instances de tomcat ne revient pas à installer deux tomcats complets dans deux repertoires différents, mais à lancer deux JVM de tomcat qui coexistent sur le même serveur mais dont les ports d'attaque sont différents...(C'est comme quand tu ouvres deux IDE eclipse : bien qu'il n'y ait qu'un seul eclipse d'installé sur ta machine tu constates qu'avec ps -ax | grep eclipse ) il existe dans ta liste des processus 2 processus java (2 JVM) .)
Cette approche me semble donc conceptuellement erronée...
Voici un descriptif que j'ai rédigé pour installer deux instances de tomcat: j'y inclu aussi les modifications du mod_jk, l'installation d'un manager, etc... des infos que tu pourras sauter(surtout pour le mod_jk si tu n'as pas d'apache pluggé à tomcat)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94 ########################################################################### #### Installation de plusieurs instance de tomcat sur une seule machine.### ########################################################################### #----------------------------------------------------- #Soit $CATALINA_HOME le répertoire de base de tomcat. #------------------------------------------------------ #S'assurer que $CATALINE_HOME et que $JAVA_HOME existe mkdir $CATALINA_HOME/otherInstances mkdir $CATALINA_HOME/otherInstances/tomcat2 mkdir $CATALINA_HOME/otherInstances/tomcat2/webapps mkdir $CATALINA_HOME/otherInstances/tomcat2/logs mkdir $CATALINA_HOME/otherInstances/tomcat2/temp mkdir $CATALINA_HOME/otherInstances/tomcat2/server mkdir $CATALINA_HOME/otherInstances/tomcat2/server/webapps mkdir $CATALINA_HOME/otherInstances/tomcat2/work #Copier le contenu du repertoire conf de $CATALINA_HOME dans le répertoire ..../tomcat2/conf cd $CATALINA_HOME cp -R conf otherInstances/tomcat2/ cp -R webapps/ROOT/ otherInstances/tomcat2/webapps/ #Editer le fichier .../tomcat2/conf/server.xml : 1) Incrémenter de 100 la valeur du port d'arrêt du server (généralement on passe de 8005 à 8105) 2) Commentez le connecteur HTTP : <Connector port="8080"....> 3) Augmenter de 100 le port du connecteur AJP1.3. (généralement on passe de 8009 à 8109) 4) Dans le host de votre choix (localhost par défaut) mettre à jour appBase="...../tomcat2/webapps/" #Editer le fichier workers.properties (dans $CATALINA_HOME/conf/jk) et rajouter : worker.list=tomcat2 worker.tomcat2.port=8109 worker.tomcat2.host=localhost worker.tomcat2.type=ajp13 ################################################## ###Installation d'un manager pour cette instance # ################################################# Editer le fichier mod_jk.conf (présent dans le sous-repertoire conf ou conf/jk de $CATALINA_HOME) et rajouter: Jkmount /manager2/* tomcat2 #Copier le répertoire $CATALINA_HOME/server/webapps/manager dans ......./tomcat2/server/webapps/manager (le nom du rep. manager doit être remplacer par manager2) cp -R $CATALINA_HOME/server/webapps/manager $CATALINA_HOME/otherInstances/tomcat2/server/webapps/manager #Copier le fichier manager.xml de $CATALINA_HOME/conf/Catalina/localhost dans ...../tomcat2/conf/Catalina/localhost/manager2.xml cp $CATALINA_HOME/conf/Catalina/localhost/manager.xml $CATALINA_HOME/otherInstances/tomcat2/conf/Catalina/localhost/manager2.xml #Editer le fichier nouvellement copié et mettre à jour docBase="../server/webapps/manager2"" (Le manager de la nouvelle instance de Tomcat sera accessible depuis l'url http://monNomDeDomaine/manager2/html) ############################################ ### Script de démarrage de l'instance ##### ############################################ #Créer un script de démarrage et d'arrêt de la deuxième instance de tomcat (tomcat2). #!/bin/bash #SCRIPT A PARFAIRE!!! export JAVA_HOME="/usr/local/j2sdk" export CATALINA_HOME="/usr/local/tomcat" export CATALINA_BASE="$CATALINA_HOME/otherInstances/tomcat2" case "$1" in start) if [ -f $CATALINA_HOME/bin/startup.sh ]; then echo $"Starting Tomcat2..." su -l wwwadm -c "(export JAVA_HOME=/usr/local/j2sdk; export CATALINA_HOME=/usr/local/tomcat; export CATALINA_BASE=/usr/local/tomcat/otherInstances/tomcat2; /usr/local/tomcat/bin/startup.sh)" fi ;; stop) if [ -f $CATALINA_HOME/bin/shutdown.sh ]; then echo $"Stopping Tomcat2..." su -l wwwadm -c "(export JAVA_HOME=/usr/local/j2sdk; export CATALINA_HOME=/usr/local/tomcat; export CATALINA_BASE=/usr/local/tomcat/otherInstances/tomcat2; /usr/local/tomcat/bin/shutdown.sh)" fi ;; *) echo $"Usage: $0 {start|stop}" echo Usage : $0 "{start | stop}" ;; esac - Faire un apache graceful (pour le rafraichissement du mod_jk.conf). - Faire un tomcat2 start. (je propose de mettre le script tomcat2 dans /etc/init.d et l'inclure au systeme V via chkconfig).
Comment indiquer à Hibernate de ne pas utiliser la CGLIB afin de ne plus avoir de fuite mémoire ?Envoyé par TonioLeRital
Merci d'avance.![]()
il y a tout d'abord le paramètre suivant :Envoyé par Mister Nono
hibernate.cglib.use_reflection_optimizer=false
ce qui force hibernate à utiliser le mécanisme de proxy du JDK (api reflectivité) plutot que celui de la CGlib.
Mais de ce que j'avais pratiqué cela ne suffisait pas car dans les version 2 et 3.0 il y a de la dépendance "en dur" vers la CGLIB néanmoins les versions futures devait pouvoir s'en affranchir... je n'ais pas vérifié depuis... mais ça sent mauvais!!!
As-tu essayé de changer de JVM pour voir si cela résoud tes problèmes...
j'ai lu assez souvent que la JVM de BEA est plus optimisée pour un usage de type serveur, mais personnellement celle d'IBM arrive largement en premier sur mes tests de montée en charge.
voilà,
tiens moi au courant.
a+
Merci pour la réponse.
J'ai donc ajouté ce tag dans le fichier de configuration de Hibernate :
Ce qui m'étonne, c'est que j'utilise Hibernate 3 et que ce problème n'est pas été réglé par rapport à la version 2.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2<property name="hibernate.cglib.use_reflection_optimizer">false</property>
Pourquoi ?
Merci.![]()
En effet, je ne disais pas que "ça sent mauvais" à la légère, car il me semblait avoir lu qu'ils n'ont pas réussi à rompre leur dépendance avec la CGlib alors qu'ils s'y étaient engagés, par contre...Envoyé par Mister Nono
As-tu essayé de réinjecter dans tes .jar la dernière version de la CGlib (2.2 version beta), peut-être ont-ils "colmaté leur fuite"... mais attention garde toujours l'ancienne version sous la main même si cela semble fonctionner...
Comment sais-tu qu'il y a une fuite mémoire? tu utilises quel outils le cas échéant?
Partager