Quelles sont les causes de PermGen OutOfMemoryError sur JBoss?

8

Quelle est la cause sous-jacente d'une erreur PermGen OutOfMemoryError dans JBoss?

J'exécute JBoss AS 4.2.2 dans mon environnement de développement, et cela se produit après le redéploiement de mon application Web un grand nombre de fois.

Le blog de Christian Vest Hansen donne des options JVM qui aident beaucoup , mais ne résolvent pas complètement le problème:

-XX:+UseConcMarkSweepGC
-XX:+CMSPermGenSweepingEnabled
-XX:+CMSClassUnloadingEnabled
-XX:MaxPermSize=128m
Peter Hilton
la source

Réponses:

5

Comme déjà mentionné, vous rencontrez probablement des fuites de chargeurs de classe. Pour une raison quelconque, vos classes ne sont pas déchargées. Cela peut se produire pour deux raisons

  • Les objets desdites classes existent toujours sur le tas, les objets référencent toujours leur classe, ou
  • Le chargeur de classe est référencé quelque part, pour une raison quelconque, les chargeurs de classe référencent leurs classes afin de ne pas les charger deux fois

Il n'y a pas de solution universelle à ce problème. Un outil utile pour vous aider à trouver la cause principale est l' outil Eclipse Memory Analyzer Tool , que vous pouvez appliquer à un vidage de tas de votre machine virtuelle Java (vous pouvez activer les vidages de tas sur les MOO avec l'option -XX: + HeapDumpOnOutOfMemoryError). Commencez peut-être à rechercher des objets java.lang.Class à partir de votre application Web pour voir pourquoi ils sont maintenus en vie. Malheureusement, PermGen ne fait normalement pas partie d'un vidage de tas JVM, vous ne pouvez donc qu'essayer de trouver des artefacts corrélatifs dans le reste du tas (les objets de classe ne sont pas stockés dans PermGen si je ne me trompe pas, seul le code d'octets réel l'est, veuillez corrigez-moi si je me trompe).

HTH.

Edit:
Dave Cheney suggère dans un commentaire que les objets java.lang.Class font en effet partie de PermGen, et ne sont pas inclus dans un vidage de tas de hotspot normal. Sauf si vous disposez d'une machine virtuelle Java qui écrit ces informations dans le vidage de tas, vous aurez besoin d'une approche différente. Vous pouvez toujours rechercher des instances de vos objets, mais si vous perdez des classes / chargeurs de classe (ils s'impliquent malheureusement tous les deux), il semble que vous devez rechercher d'autres signes (objets de métadonnées de JBoss, etc.).

falstro
la source
1
Je suis assez certain que les objets Class sont stockés dans PermGen (c'est-à-dire les objets qui sont des instances de Class). Il existe une zone distincte sur la machine virtuelle Java Sun appelée Cache de code, où est stocké le code qui a été compilé en code machine. Le PermGen et le cache de code font tous deux partie de la mémoire Non Heap que vous pouvez voir en utilisant des outils comme jconsole
Dave Cheney
@Dave Cheney: Vous avez raison. Les objets de classe divulgués coincés dans PermGen sont généralement la cause du problème de l'OP.
Eddie
roe, bien que je ne pense pas que le contenu du PermGen soit écrit dans le vidage de tas (ceci utilise la JVM Sun, je n'ai pas beaucoup d'expérience avec les autres), le format de vidage hprof sait certainement des choses comme, combien classes ont été chargées, combien de chargeurs de classe, etc. Vous pouvez le voir lors de l'ouverture de hprof dans Eclipse Memory Analyzer). Ce qui n'est probablement pas écrit, ce sont les grandes données de classe binaire qui composent le code d'octet java, ce que vous voyez dans le vidage de tas est le «stub» de l'instance de classe stockée sur PermGen.
Dave Cheney
2

La cause sous-jacente est les références aux classes qui ont été rejetées et qui fuient en dehors de leur chargeur de classe, empêchant la JVM de décharger ces classes du perm gen. Ces drapeaux que vous utilisez peut entraîner la machine virtuelle Java à des classes de purge agressive qui sont unloadable, mais il ne résoudra pas le problème sous - jacent.

Il y a une bonne et complexe explication ici

Dave Cheney
la source
1

La cause de l'erreur PermGen OutOfMemory est le redéploiement de l'application. La cause sous-jacente est la fuite d'objets de classe dans PermGen à partir des redéploiements.

Bien entendu, la solution consiste à redémarrer la JVM après un certain nombre de redéploiements.

Il s'agit d'un problème très difficile à résoudre totalement, bien qu'avec certains détournements, vous puissiez souvent apporter de grandes améliorations. Voici par où commencer: lorsque votre application Web est arrêtée, assurez-vous que:

  • tous les threads que vous avez démarrés sont arrêtés
  • tous les ThreadPools que vous avez démarrés sont fermés
  • toutes les références statiques que vous pouvez libérer sont publiées

Ce sont certaines des choses qui peuvent provoquer un objet Class à être piégé dans PermGen.

Notez également que toutes les JVM (ou toutes les versions de JVM) ne seront pas des objets de classe GC dans PermGen. Si vous exécutez une JVM ou une version d'une JVM qui ne contiendra pas d'objets de classe GC dans PermGen, votre seul choix est de redémarrer la JVM après un certain nombre de redéploiements. Cela ne s'applique probablement pas à vous, compte tenu des options JVM que vous mentionnez.

Eddie
la source