{"id":42,"date":"2007-10-14T16:51:38","date_gmt":"2007-10-14T16:51:38","guid":{"rendered":"http:\/\/blog.milamberspace.net\/index.php\/2007\/10\/14\/sap-memory-analyzer-voila-un-vrai-outil-pour-analyser-des-heap-dump-java-42.html"},"modified":"2007-10-14T18:44:58","modified_gmt":"2007-10-14T18:44:58","slug":"sap-memory-analyzer-voila-un-vrai-outil-pour-analyser-des-heap-dump-java","status":"publish","type":"post","link":"https:\/\/blog.milamberspace.net\/index.php\/2007\/10\/14\/sap-memory-analyzer-voila-un-vrai-outil-pour-analyser-des-heap-dump-java-42.html","title":{"rendered":"SAP Memory Analyzer : voil\u00e0 un vrai outil pour analyser des Heap Dump Java !"},"content":{"rendered":"<p>Vous avez d\u00e9velopp\u00e9 une application JEE, et depuis son passage en production au moins une fois par jour il y a une erreur Java \u00ab OutOfMemoryError \u00bb. La premi\u00e8re r\u00e9action a \u00e9t\u00e9 de dire : mauvaise configuration de la taille maximale de la JVM&#8230; vous avez pr\u00e9conis\u00e9 1Go de Max Heap Size, cela n&rsquo;a pas fonctionn\u00e9, l&rsquo;erreur OOME arrive encore&#8230; Alors on est pass\u00e9 \u00e0 2Go&#8230; Toujours l&rsquo;erreur d&rsquo;OOME&#8230; Aie, et que faire&#8230;<\/p>\n<p>Quand vous \u00eates \u00e0 ce point, vous pouvez \u00eatre certain que vous avez une fuite de m\u00e9moire (memory leaks) quelque part. Oh, ce n&rsquo;est pas que vous \u00eates un mauvais d\u00e9veloppeur \ud83d\ude09 et que vous ne savez pas bien gerer la m\u00e9moire, en effet, parfois un probl\u00e8me de fuite de m\u00e9moire peut survenir \u00e0 cause d&rsquo;une fonctionnalit\u00e9 activ\u00e9e du serveur d&rsquo;applications de production et qui rentre en \u00ab conflit \u00bb avec une brique de l&rsquo;application. (Je citerai un exemple v\u00e9cu : le cache (activ\u00e9) JDBC de la source de donn\u00e9es WebSphere 5.1 et un framework maison de mapping O\/R)<\/p>\n<p>Quand on a un probl\u00e8me d&rsquo;OutOfMemory, on commence souvent par activer le mode verbeux du Garbage Collector (GC), c&rsquo;est une tr\u00e8s bonne id\u00e9e, cela permet d&rsquo;avoir une petite id\u00e9e sur le d\u00e9roulement du probl\u00e8me de m\u00e9moire  <em>(on peut utiliser l&rsquo;outil Extensible Verbose Toolkit d&rsquo;IBM pour ce travail, cf r\u00e9f\u00e9rences)<\/em>. Cependant c&rsquo;est insuffisant pour trouver la cause du probl\u00e8me<em>.<\/em> Quelques recherches sur Internet vous apprennent qu&rsquo;il est possible d&rsquo;avoir une image de la m\u00e9moire Java avec la g\u00e9n\u00e9ration d&rsquo;un \u00ab heap dump \u00bb, ensuite il suffit de l&rsquo;analyser pour trouver la cause de la fuite de m\u00e9moire. Facile \u00e0 \u00e9crire, mais dur \u00e0 faire&#8230;<\/p>\n<p><!--more--><\/p>\n<p><strong>Commen\u00e7ons par la g\u00e9n\u00e9ration du heap dump.<\/strong> La bonne nouvelle, c&rsquo;est que depuis les versions Java 1.4.2 update 12, Java 5 update 07 et Java 6, la g\u00e9n\u00e9ration de heap dump est \u00ab devenu \u00bb facile. Pour avoir un heap dump automatique d\u00e8s que vous avez une erreur OOME, il faut simplement ajouter ce param\u00e8tre <strong>-XX:+HeapDumpOnOutOfMemoryError<\/strong> dans les arguments de la JVM. La mauvaise nouvelle, c&rsquo;est que pour les versions ant\u00e9rieures, c&rsquo;est plus difficile d&rsquo;obtenir un heap dump. Cela d\u00e9pend de l&rsquo;\u00e9diteur de la JVM que vous utilisez (IBM, BEA, Sun, HP, etc), il faut se reporter sur le site de l&rsquo;\u00e9diteur pour trouvez la bonne recette&#8230;<\/p>\n<p>Une fois que l&rsquo;on a trouv\u00e9 le bon param\u00e8tre pour g\u00e9n\u00e9rer son heap dump, il ne reste plus qu&rsquo;\u00e0 le mettre en production et attendre l&rsquo;erreur fatal d&rsquo;OOME. Quand celle-ci arrive, on attend la g\u00e9n\u00e9ration du fichier qui peut prendre plusieurs minutes car le fichier aura la taille de la JVM au moment de l&rsquo;erreur. Donc si la taille maximum est \u00e0 1Go, le fichier va faire 1Go.<\/p>\n<p><strong>Maintenant que l&rsquo;on a son fichier heap dump, il faut l&rsquo;analyser&#8230;<\/strong>et l\u00e0 aussi c&rsquo;est pas simple. Il existe diff\u00e9rents moyens, allant du mode texte (via Hprof) vers des outils tels que Heap Analyzer de IBM ou bien HAT (ou JHAT maintenant) de Sun. Le gros probl\u00e8me de ses outils, c&rsquo;est que c&rsquo;est quasiment impossible d&rsquo;ouvrir un heap dump d&rsquo;1Go avec. Vous avez un OutOfMemoryError de l&rsquo;outil \ud83d\ude09<\/p>\n<p>La bonne nouvelle c&rsquo;est que l&rsquo;\u00e9diteur SAP a pens\u00e9 \u00e0 nous, \u00e0 travers son outil d&rsquo;analyse Memory Analyzer. Ce dernier est bas\u00e9 sur l&rsquo;environnement RCP d&rsquo;Eclipse. Il ouvre sans difficult\u00e9 un heap dump de 1Go, car il analyse le fichier heap dump petit \u00e0 petit et en cr\u00e9ant ses propres fichiers d&rsquo;index. <em>(Il faut compter environ 1h30 pour ouvrir un fichier 1,2Go sur un portable Vista avec 2Go de RAM, Core 2 Duo 2GHz)<\/em><\/p>\n<p>Memory Analyzer dispose de nombreuses fonctionnalit\u00e9s, dont l&rsquo;une qui va nous int\u00e9resser particuli\u00e8rement : la d\u00e9tection de fuite de m\u00e9moire (find memory leaks). De plus il dispose de tutoriaux pour aider \u00e0 l&rsquo;analyse de fichier heap dump.<\/p>\n<p>Voici quelques captures d&rsquo;\u00e9cran qui en diront plus que mes longs discours :<\/p>\n<p><strong>D\u00e9tails d&rsquo;un heap dump.<\/strong><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"\/wp-content\/images\/memory-analyzer-01-img\/sap-memory-analyzer-01.gif\" alt=\"D\u00e9tails d'un heap dump\" align=\"left\" border=\"1\" height=\"439\" width=\"569\" \/><br clear=\"left\" \/><br \/>\n<strong>Histogramme, d\u00e9tails par classe : nombre d&rsquo;objets, taille la plus petite de l&rsquo;objet, taille des objets<\/strong><\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/images\/memory-analyzer-01-img\/sap-memory-analyzer-03.gif\" alt=\"Histogram - Voir les classes, le nombre d'objets,  la plus petite taille de l'objet et la taille totale des objets\" align=\"left\" border=\"1\" \/><br clear=\"left\" \/><br \/>\n<strong>Inspector pour avoir le d\u00e9tail et le contenu d&rsquo;un objet<\/strong><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"\/wp-content\/images\/memory-analyzer-01-img\/sap-memory-analyzer-04.gif\" alt=\"Inspector\" align=\"left\" border=\"1\" height=\"863\" width=\"564\" \/><br clear=\"left\" \/><\/p>\n<p><strong>La d\u00e9tection de fuite de m\u00e9moire<\/strong>, ici un objet d\u00e9tient \u00e0 lui tout seul 657 Mo sur 1024 Mo ! Cela sent le memory leaks&#8230;<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/images\/memory-analyzer-01-img\/sap-memory-analyzer-05.gif\" alt=\"D\u00e9tection de fuite de m\u00e9moire (memory leaks)\" align=\"left\" border=\"1\" \/><br clear=\"left\" \/><\/p>\n<p><strong>Analyse de la fuite m\u00e9moire<\/strong>, la cause ici semble \u00eatre une liste HashMap de + de 490000 objets.<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/images\/memory-analyzer-01-img\/sap-memory-analyzer-02.gif\" alt=\"Analyse d'une fuite de m\u00e9moire\" align=\"left\" border=\"1\" \/><br clear=\"left\" \/><br \/>\n<u><strong><br \/>\n[Quelques pointeurs]<\/strong><\/u><\/p>\n<ul>\n<li><a href=\"https:\/\/www.sdn.sap.com\/irj\/sdn\/wiki?path=\/display\/Java\/Java+Memory+Analysis\">SAP Memory Analyzer<\/a><\/li>\n<li><a href=\"http:\/\/blogs.sun.com\/alanb\/entry\/heap_dumps_are_back_with\">Heap dumps are back with a vengeance! <\/a><\/li>\n<li><a href=\"https:\/\/hat.dev.java.net\/doc\/README.html\">HAT &#8212; The Java Heap Analysis Tool<\/a><\/li>\n<li><a href=\"http:\/\/www.alphaworks.ibm.com\/tech\/heaproots\">IBM : HeapRoots : A tool for debugging memory leaks in Java applications through analysis of \u00ab\u00a0heap dumps.\u00a0\u00bb<\/a><\/li>\n<li><a href=\"http:\/\/www.alphaworks.ibm.com\/tech\/heapanalyzer\">IBM : HeapAnalyzer : A graphical tool for discovering possible Java heap leaks.<\/a><\/li>\n<li><a href=\"http:\/\/www-1.ibm.com\/support\/docview.wss?rs=180&amp;context=SSEQTP&amp;q1=heapdump+solaris&amp;uid=swg21190608&amp;loc=en_US&amp;cs=utf-8&amp;lang=en\">IBM : Using HeapAnalyzer to analyze Java heap usage and detect possible Java heap leak<\/a><\/li>\n<li><a href=\"http:\/\/dev2dev.bea.com\/pub\/a\/2005\/06\/memory_leaks.html\">BEA : Memory Leaks, Be Gone!<\/a><\/li>\n<li><a href=\"http:\/\/www.ibm.com\/developerworks\/java\/library\/j-ibmtools1\/\">Java diagnostics, IBM style, Part 1: Introducing the IBM Dump Analyzer for Java<\/a><\/li>\n<li><a href=\"http:\/\/www.ibm.com\/developerworks\/web\/library\/j-ibmtools2\/?S_TACT=105AGX54&amp;ca=dnw-839\">Java diagnostics, IBM style, Part 2: Garbage collection with the Extensible Verbose Toolkit<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Vous avez d\u00e9velopp\u00e9 une application JEE, et depuis son passage en production au moins une fois par jour il y a une erreur Java \u00ab OutOfMemoryError \u00bb. La premi\u00e8re r\u00e9action a \u00e9t\u00e9 de dire : mauvaise configuration de la taille maximale de la JVM&#8230; vous avez pr\u00e9conis\u00e9 1Go de Max Heap Size, cela n&rsquo;a pas &hellip; <a href=\"https:\/\/blog.milamberspace.net\/index.php\/2007\/10\/14\/sap-memory-analyzer-voila-un-vrai-outil-pour-analyser-des-heap-dump-java-42.html\" class=\"more-link\">Continuer la lecture de <span class=\"screen-reader-text\">SAP Memory Analyzer : voil\u00e0 un vrai outil pour analyser des Heap Dump Java !<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[39,35,38,42,17,41,36,40],"tags":[],"class_list":["post-42","post","type-post","status-publish","format-standard","hentry","category-bea","category-heap-dump","category-ibm","category-j2ee","category-java","category-jee","category-performance","category-sun"],"_links":{"self":[{"href":"https:\/\/blog.milamberspace.net\/index.php\/wp-json\/wp\/v2\/posts\/42","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.milamberspace.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.milamberspace.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.milamberspace.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.milamberspace.net\/index.php\/wp-json\/wp\/v2\/comments?post=42"}],"version-history":[{"count":0,"href":"https:\/\/blog.milamberspace.net\/index.php\/wp-json\/wp\/v2\/posts\/42\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.milamberspace.net\/index.php\/wp-json\/wp\/v2\/media?parent=42"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.milamberspace.net\/index.php\/wp-json\/wp\/v2\/categories?post=42"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.milamberspace.net\/index.php\/wp-json\/wp\/v2\/tags?post=42"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}