Accueil > Java / JEE > Analyse de la mémoire d’une application Java

Analyse de la mémoire d’une application Java

Lorsque vous voulez analyser la mémoire de votre programme java, le jdk 6 propose des outils puissants et relativement simples à utiliser.

Pré-requis :

Il vous faut le jdk5 minimum.
Il vous faut télécharger le plugin ‘eclipse memory analyzer‘ pour Eclipse, à installer depuis cet url http://download.eclipse.org/technology/mat/0.8/update-site/ à saisir dans le menu d’aide d’Eclipse, puis ‘mise à jour’.

La plupart des nouvelles fonctions de supervision sont regroupé via l’interface JMX, c’est pour cela qu’il est nécessaire d’activer JMX sur votre programme.

Pour cela, dans les options de ligne de commande du lancement de votre application, rajouter les options:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8084
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false

indiquant à la JVM d’activer JMX sans authentification et accessible via le port 8084 (que vous pouvez changer bien sur).

1ère étape : Obtenir un dump de la mémoire

Il existe plusieurs façons d’obtenir un dump :

  • Utilisation de la console JMX fournie avec le jdk

Dans un shell, tapez ‘jconsole‘.

login de la jconsole

login de la jconsole

Cochez ‘Remote Process‘, et saisir ‘localhost:8084‘ et cliquer sur ‘connect‘.
Ensuite dans l’onglet ‘MBeans‘, déroulez dans le menu de gauche la partie ‘com.sun.management.HotSpotDiagnostic.Operations‘ et sur la partie de droite, apparait une méthode ‘dumpHeap‘.

Dumper la mémoire

Dumper la mémoire

Le paramètre ‘P0‘ représente le chemin du fichier dump sur le disque à générer, et le paramètre ‘p1‘ doit rester à ‘true’, signifiant par cette valeur que nous voulons uniquement les objets vivants.
Appuyez sur le bouton ‘dumpHeap‘ et le fichier se génère à l’endroit spécifié.

  • Configurer notre programme java pour générer un dump lors d’une exception ‘OutOfMemoryError’.

Pour cela, il faut rajouter dans les options du programme ‘-XX:+HeapDumpOnOutOfMemoryError‘. Il générera un fichier de type « java_pidXXX.hprof » à la racine de votre application.

  • Utiliser l’outil ‘jmap‘ fourni par le jdk.

Dans un shell, tapez ‘jmap -dump:format=b,file=<fichier> <pid>‘ où <pid> est l’identifiant du process faisant tourner votre application et <fichier> est le chemin vers le fichier de dump sur le disque.
Sur un environnement 64bits, cette commande ne fonctionne pas, privilégiez alors JMX et la jconsole.

2eme étape : Analyser le dump

Il existe plusieurs façons d’analyser un dump, mais un fichier dump ne peut se lire avec un éditeur de texte, car c’est du binaire.

  • Utiliser le plugin ‘Memory analyzer‘ sous Eclipse.

Pour cela, il faut sélectionner la perspective du plugin, et ensuite cliquer sur le bouton pour ouvrir un fichier de dump.

Plugin memory analyser

Plugin memory analyser

Ensuite, il faut se laisser guider par le plugin. L’aide du plugin est très bien faite.
Pour commencer, dans le wizard qu’on nous propose, choisir ‘Leak Suspects report‘ et cliquez sur ‘Finish‘. Cette opération va déclencher une recherche des fuites mémoires possibles.

Fuite mémoire

Fuite mémoire

Le rapport ainsi produit nous indique clairement un problème avec des objets de type « Classloader » (problème typique dans des serveurs d’applications comme Tomcat).
Le gros du travail reste alors à faire, c’est à dire trouver pourquoi ces objets posent problème.
Le plugin propose également d’autres rapport intéressants:

Tableau de bord

Tableau de bord

Le rapport ‘Histogram‘ liste l’ensemble des classes de la mémoire, en nous précisant le nombre d’instances de chaque classe, le nombre d’octets pris par l’ensemble des objets de chaque classe (shallow heap) en comptabilisant les pointeurs directs uniquement, et enfin le nombre d’octets pris par l’ensemble des instances de classe en comptant cette fois en profondeur tous les objets contenus dans chaque instance (retained heap).

Par exemple, prenons le cas de la classe ArrayList. Cette classe contient principalement un tableau d’objets.
La ‘shallow heap’ d’un objet ArrayList est donc grosso modo équivalent à : taille du tableau * taille d’un pointeur (32 ou 64 bits suivant l’os).
La ‘retained heap’ d’un objet ArrayList correspond à la somme de tous les ‘shallow heap’ de l’ensemble des objets rattachés à cet objet. Prenons le cas d’un objet ArrayList de String, la retained heap est équivalent à : shallow heap de l’ArrayList + taille du tableau * retained heap d’un String.etc…

Histogram

Histogram

Le rapport ‘Dominator tree‘ liste l’ensemble des objets, ce qui nous permet de voir quels sont les objets qui prennent le plus de place en mémoire.

Dominator Tree

Dominator Tree

Ainsi, sur la capture ci dessus, on voit que l’objet ‘org.apache.catalina.loader.WebappClassLoader @ 0x68c1c60′ prend pas moins de 1,7 megaoctets à lui seul.
Lorsque l’on clique sur un objet, on peut voir dans l’onglet ‘attributes‘ les attributs de l’objet.

Enfin, le rapport ‘Duplicate classes‘ nous indique les mêmes classes qui ont été chargés en plusieurs exemplaire, ce qui permet de nous éclairer sur des optimisations à faire, et sur des problemes de classloader.

Quelques trucs et astuces sur l’utilisation de ce plugin :

Sur un objet ou une classe, appuyez sur le bouton droit de la souris et un menu apparait.
Si vous voulez connaître les classes qui référencent l’objet que vous avez sélectionné, choisissez ‘Show Objects by class > by incoming references‘.

Incoming reference

Incoming reference

Dans la capture, on peut voir que la classe ‘java.util.ArrayList‘ est utilisée dans la classe ‘java.beans.MethodDescriptor‘.

Si vous voulez connaître les objets que sont référencés par l’objet que vous avez sélectionné, choisissez ‘List Objects > with outgoing references‘.

Outgoing reference

Outgoing reference

Dans cette capture, on peut voir tous les objets en attributs direct de l’objet sélectionné, et voir la taille. Par exemple, on voit que c’est une ‘hashtable’ qui prend la majorité de la mémoire de l’objet sélectionné.

  • Utiliser l’outil ‘jhat‘ du jdk qui donne les mêmes informations que le plugin Eclipse mais ces informations parcours à l’aide d’un navigateur web, et l’ergonomie en patie. Les leaks ne sont pas indiqués, c’est à nous de les trouver.

Dans un shell, tapez ‘jhat -J-Xmx512m <fichier de dump sur le disque>‘. Je passe une valeur xmx car si le fichier de dump est gros, il faut de la mémoire pour l’analyser.
jhat analyse alors le dump, et lance un mini serveur web sur le port 7000. Il ne reste plus qu’à lancer un navigateur web à l’adresse ‘http://localhost:7000&rsquo; pour voir apparaître cet écran.

jhat

jhat

On retrouve certaines opérations disponibles dans le plugin eclipse, comme la partie ‘histogram‘.

  1. Aucun commentaire pour l’instant.
  1. No trackbacks yet.

Laisser un commentaire