Analyser des problèmes de mémoire

Description

Environnement
Experience Manager

Problème/Symptômes
L’application Java s’exécute plus lentement et finit par manquer de mémoire ou une erreur s’affiche dans les journaux ou dans la sortie de console. OutOfMemoryError: Java heap space ou OutOfMemoryError: gc overhead limit exceeded.

Résolution

Cause

De tels problèmes peuvent avoir de nombreuses causes.

Une cause possible est que l'application java, dans notre cas, CRX / CQ a été lancée à partir de la ligne de commande avec les paramètres de mémoire de tas par défaut de Java. Cela signifie que le paramètre jvm -Xmx n’a pas été spécifié. CRX ou CQ ont besoin d’au moins 256 Mo de segments alloués pour s’exécuter. S’il s’agit bien de ce problème, assurez-vous que les paramètres de mémoire de segment sont définis à partir de la ligne de commande. Exemple :

java -Xmx512m -jar *.jar

Si ce n’est pas le cas, votre application peut conserver trop d’objets sans les libérer pour la récupération de l’espace mémoire. Cela s’appelle une fuite de mémoire. Voir ici pour plus d’informations. Consultez la section ci-dessous sur l’analyse des problèmes de mémoire dans les applications Java.

Créer un vidage de tas
Générer automatiquement un vidage de tas

Pour créer automatiquement un vidage de tas en cas de manque de mémoire, vous pouvez ajouter le paramètre jvm . -XX:+HeapDumpOnOutOfMemoryError pour générer automatiquement un vidage de tas lorsque l’application renvoie une erreur OutOfMemoryError. Par exemple,

java -Xmx256m -XX:+HeapDumpOnOutOfMemoryError -jar *.jar

Cela génère un fichier de vidage de tas (java_...hprof) dans le répertoire de travail du processus chaque fois que le processus java manque de mémoire. celui-ci peut continuer à s’exécuter une fois l’image mémoire générée. En règle générale, un fichier d’image mémoire suffit à analyser le problème.

Remarque : si vous utilisez le script crx-quickstart/server/start pour démarrer votre instance CRX, vous pouvez ajouter -XX:+HeapDumpOnOutOfMemoryError à la variable CQ_JVM_OPTS (vérifiez que cette variable n’est pas non plus commentée). Par exemple :

CQ_JVM_OPTS='-XX:+HeapDumpOnOutOfMemoryError'

Après avoir ajouté ce paramètre et redémarré l’instance CRX, vérifiez que la nouvelle option jvm est définie. Exécutez ps -ef | grep java à partir de la ligne de commande. Vérifiez ensuite si vous voyez -XX:+HeapDumpOnOutOfMemoryError comme paramètre du processus Java CRX.

Si vous devez spécifier un autre répertoire pour générer l’image mémoire en raison de restrictions d’espace disque, vous pouvez ajouter le paramètre -XX:HeapDumpPath=/path/to/generate/heapdump pour indiquer au jvm où placer le fichier.

Voir ici pour obtenir une référence des paramètres jvm liés au débogage.

Générer manuellement un vidage de tas

JVM Sun/Oracle

Pour générer manuellement une image mémoire, exécutez cette commande (vous trouverez jmap et jps dans le dossier bin de votre répertoire racine jdk) :

  1. recherchez le pid du processus java pour lequel vous générez un vidage de tas.

    • Sous Unix ou Linux, cela peut être effectué avec ps -ef | grep java ou jps -l
    • Sous Windows, cela peut être effectué en ouvrant le gestionnaire de tâches, puis appuyez sur Ctrl+Shift+Esc puis accédez à Affichage = Sélectionner des colonnes = PID (identifiant de processus) ou jps -l
  2. Exécutez la commande jmap ci-dessous, remplacez /path/to/generate/heapdumpfile.hprof par l’emplacement où vous souhaitez générer le fichier d’image mémoire, puis remplacez 1234 par le pid que vous avez consulté à l’étape précédente.

    jmap -dump:format=b,file=/path/to/generate/heapdumpfile.hprof 1234
    

IBM JVM

Vous devrez d’abord modifier les paramètres JVM par défaut concernant les agents de vidage pour générer les vidages corrects sur le signal de l’utilisateur. Il existe plusieurs types de vidage, mais vous avez généralement besoin du vidage du système complet pour effectuer une analyse approfondie de la mémoire. Ajoutez les arguments suivants :

Xdump:heap:opts=PHD+CLASSIC:events=user -Xdump:system:events=user

Cet événement "utilisateur" se produit lorsque la JVM reçoit le signal SIGQUIT (Linux, AIX®, z/OS® et i5/OS™) ou SIGBREAK (Windows) du système d’exploitation.

Pour plus d’informations, consultez la documentation fournisseur disponible ici.

Avertissement : Les fichiers de vidage de tas sont volumineux et peuvent atteindre la même taille sur le disque que votre configuration de paramètre max heap -Xmx jvm . Assurez-vous que l’espace disque alloué au répertoire dans lequel le fichier de vidage est généré est suffisant.

Analyse du vidage du tas

EclipseMAT (Eclipse Memory Analyzer) est un bon outil pour analyser les vidages de tas : http://www.eclipse.org/mat/

Cet outil ne peut pas analyser les vidages générés IBM JVM. Pour ceux-là, il y a plusieurs possibilités. IBM HeapAnalyzer s’en sortira bien pour les images mémoire au format PHD ou classique.

Pour une analyse complète de vidage du système, utilisez la méthode IBM Support Assistant Workbench, avec Outils de surveillance et de diagnostic IBM pour Java - Memory Analyzer version 1.2 installé sur le dessus.

Histogramme du tas

L’histogramme du tas est une mesure simple du nombre d’objets actifs et de la mémoire utilisés par classe Java. Malheureusement, selon l’installation de Java, les outils requis peuvent ne pas être disponibles ou ne pas toujours fonctionner. Pour créer un histogramme de tas, vous devez d’abord connaître l’identifiant du processus Java. Pour l’obtenir, exécutez ps ou (le cas échéant), exécutez :

jps -l

Cet outil Java récupère les ID de processus de tous les processus Java en cours d’exécution. Exemple :

327
3332 sun.tools.jps.Jps
3313 crx-quickstart-....jar

À présent, exécutez la commande suivante :

jmap -histo 3313

La liste est triée en fonction de la mémoire totale requise (superficielle : à l’exception des objets référencés). Les 20 premières lignes de la sortie sont les plus intéressantes. Exemple de sortie :

JVM version is 1.5.0_20-141
Iterating over heap. This may take a while...
Warning: skipping invalid TLAB for thread t@62211
Warning: skipping invalid TLAB for thread t@62467
...
SizeCountClass description
-------------------------------------------------------
1059290412916byte
1028584075255* ConstMethodKlass
628317658388char
604230414928int
4995752116201* SymbolKlass
422089675255* MethodKlass
41965126969* ConstantPoolKlass
29285606969* InstanceKlassKlass
26310086066* ConstantPoolCacheKlass
2395872149742org.apache.jackrabbit.core.query.lucene.DocId$PlainDocId
14760087003java.util.HashMap$Entry
139612858172java.lang.String
107023244593java.util.HashMap$Entry
75398410036short
73546454org.apache.jackrabbit.core.query.lucene.DocId
7201927502java.lang.Class
64070413348com.day.crx.persistence.tar.index.IndexEntry
...

Informations supplémentaires

Pour vous aider à analyser le problème, nous devons également connaître les informations suivantes :

  • Version CRX ou CQ, y compris une liste de tous les numéros de version des correctifs installés.
  • Système d’exploitation, fournisseur JVM et version.

Références

http://java.sun.com/javase/6/webnotes/trouble/TSG-VM/html/memleaks.html
http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp#DebuggingOptions

Sur cette page