Dites au revoir aux PermGen space
Vous travaillez sous Eclipse ? Vous utilisez un serveur d’applications intégrant Tomcat tel que JOnAS ou JBoss ? Et l’accès aux données est fait via Hibernate (même encapsulé dans la couche EJB3) ? Et pour finir, votre application contient un module web ?
Si vous avez répondu par l’affirmative à la majorité de ces questions, vous devez bien connaitre le message suivant :
PermGen space
Ceci se produit après quelques déploiements à chaud de votre application et provoque le blocage de votre serveur d’application. Après une telle erreur, il ne reste plus qu’à tuer le processus du serveur (le script d’arrêt ne fonctionnant plus) puis à le relancer.
Après avoir investigué sur le sujet, il semble que l’utilisation de bibliothèques externes qui font du chargement dynamique de classe ne soit pas compatible avec le redéploiement car l’URLClassLoader de Tomcat garde des références sur des objets dont les classes ont été chargées dynamiquement lors de l’exécution. Ce qui empêche le garbage collector de faire correctement son travail. 😉
Or Hibernate utilise la bibliothèque CGLIB pour le chargement dynamique de classe (lazy=false).
Spécifique à la JVM Sun, le PermGen space est une zone mémoire qui contient tout ce qui n’est pas géré par le garbage collector; tout ce qui est relatif au classes (leur structure: méthodes, champs, annotations…), les champs static, les chaines littérales… On spécifie le PermGen space avec les propriétés -XX:PermSize=256m et -XX:MaxPermSize=256m par exemple. Plus on a de classes différentes plus il faut augmenter la taille de cette zone mémoire.
Pour résoudre le problème, enfin pour le repousser devrais-je dire, il est possible d’ajouter le paramètre suivant lors du lancement de votre serveur d’application : -XX:MaxPermSize=256m. La taille étant à définir selon votre utilisation. Par contre, il faut éviter de mettre le paramètre -noclassgc qui empêche le garbage collector de nettoyer l’espace du PermGen.
L’autre solution est d’utiliser la JVM d’IBM ou JRockit de BEA. Mais on ne fait pas de polémique ici. 😛
https://blog.lecacheur.com/2008/06/06/dites-au-revoir-aux-permgen-space/DéveloppementHibernateeclipse,hibernateVous travaillez sous Eclipse ? Vous utilisez un serveur d'applications intégrant Tomcat tel que JOnAS ou JBoss ? Et l'accès aux données est fait via Hibernate (même encapsulé dans la couche EJB3) ? Et pour finir, votre application contient un module web ? Si vous avez répondu par l'affirmative à...SeBSébastien LECACHEUR23r0@laposte.netAdministratorLe weblogue de SeB
Effectivement, ce problème arrive malheureusement plus souvent que l’on croit. Même si ce problème n’est pas forcément lié à l’instrumentalisation des classes, il est vrai que de plus en plus de frameworks utilisent ce principe.
Si le fonctionnement des GC générationnels de la JVM Sun vous intéresse, je vous propose de consulter un article que j’ai écrit sur le blog Xebia :
http://blog.xebia.fr/2008/03/12/gc-generationnels-traditionnels-jdk6-vs-gc-garbage-first-jdk7/
De même si vous voulez comprendre le fonctionnement du load time weaving, je vous invite à consulter cet article qui décrit l’un des moyens pour y arriver : les agents java.
http://blog.xebia.fr/2008/05/02/java-agent-instrumentez-vos-classes/
Erwan,
Je connaissais déjà ton article sur l’instrumentation de classe avec Java Agent. 😉 Je t’avoue que pour le moment, je ne vois pas où je pourrai mettre en place explicitement cette technologie.
Ton article sur la présentation des GC générationnels et Gabage First est très intéressant et très clair. Merci pour le lien !
C’est bien joli tout ca, mais tu ne précise pas vraiment ou modifier ces valeurs…
Tom,
J’indique simplement qu’il faut le modifier dans le script de lancement du serveur d’application. Comme les serveurs d’applications ont chacun leur propre script de lancement et configuration, je n’ai pas donné d’exemple précis pour rester généraliste.
Tom,
Par exemple pour Tomcat le fichier catalina.sh (ou .bat selon vôtre systeme) qui se trouve dans le dossier « tomcat-xxx/bin/ ».
Par exemple en ajoutant en début de fichier la ligne suivante :
JAVA_OPTS= »-XX:PermSize=256m et -XX:MaxPermSize=256m »
Toutes fois si vous utilisez rmi avec un agent de type hyperic et que vous avez besoin de définir des paramêtres spécifiques utilisez en plus la variable CATALINA_OPTS sous peine de ne pas pouvoir arreter tomcat avec le script d’init si vous avez spécifié toutes les options (rmi y compris) dans la variable JAVA_OPTS.
Une documentation rapide sur l’utilisation des ses variables se trouve au début du fichier catalina.sh ou .bat.