{"id":36,"date":"2012-06-27T01:02:09","date_gmt":"2012-06-26T23:02:09","guid":{"rendered":"http:\/\/marko-seifert.de\/blog\/?p=36"},"modified":"2020-01-15T12:23:38","modified_gmt":"2020-01-15T10:23:38","slug":"test-1","status":"publish","type":"post","link":"http:\/\/marko-seifert.de\/blog\/?p=36","title":{"rendered":"Was tun bei OutOfMemory \u2013 Teil 2: Analyse"},"content":{"rendered":"<p>Nicht selten kommt es vor, dass Speicherprobleme erst im Wirkbetrieb auftreten. Die Gr\u00fcnde daf\u00fcr sind oft, dass das System nicht ausreichend oder gar nicht unter realen Lastbedingungen getestet wurde.<br \/>\nBei Systemen mit redaktionellen Inhalten (z. B. Content Management Systeme) ergibt sich aus der steigenden Anzahl der Inhalte in Verbindung mit Abh\u00e4ngigkeiten und Caching\u00a0 eine wachsende Belastung. In der Testphase sind diese Inhalte in der Komplexit\u00e4t und Masse meist noch nicht verf\u00fcgbar.<\/p>\n<p><!--more--><\/p>\n<p>Wie bei vielen anderen Problemen auch, kann man OutOfMemory in zwei Kategorien einteilen:<\/p>\n<ul>\n<li>Problem tritt regelm\u00e4\u00dfig auf:\u00a0 Das Problem tritt immer nach gewisser Zeit oder beim Aufruf gewisser Methoden auf. Diese Art von Fehler ist meist gut nachstellbar und im Algemeinen auch schnell behoben. Die Ursache sind meist Programmierfehler.<\/li>\n<li>Problem tritt sporadisch auf: Das Problem tritt immer mal wieder auf. Davor und danach l\u00e4uft das System\u00a0 weitergehend stabil. Hier ist extrem schwierig den Fehler nachzustellen und die Ursachen daf\u00fcr einzugrenzen. Man sucht hier wortw\u00f6rtlich die Nadel im Heuhaufen.<\/li>\n<\/ul>\n<p>Geraden f\u00fcr den Typ 2 ist ein strukturiertes Vorgehen von gro\u00dfer Bedeutung. Es empfiehlt sich, ein Vorgehensmodel zu definieren und zu dokumentieren. Bei neuen Erkenntnissen wird das Vorgehensmodel erweitert oder ggf. angepasst. F\u00fcr jeden Vorgehensschritt gibt es eine konkrete Aufgabe, die verschiedene Ergebnisse liefert. Dieses Vorgehen hat mehrere Vorteile:<\/p>\n<ul>\n<li>Es gibt einen roten Faden: Die Komplexit\u00e4t ist meist sehr hoch. Wenn man nicht strukturiert die Probleme angeht, l\u00e4uft man Gefahr, sich zu verzetteln.<\/li>\n<li>Das Wissen kann besser auf mehrere Mitarbeiter verteilt werden: Sollte ein Mitarbeiter mal ausfallen (wegen Krankheit oder Urlaub) k\u00f6nnen andere Mitarbeiter diese Aufgabe \u00fcbernehmen.<\/li>\n<li>Es gibt Material f\u00fcr das Management: Das Management kann sich oft nicht vorstellen, warum es so lange dauert, das Problem zu l\u00f6sen. \u00dcber das Vorgehensmodel ist gekl\u00e4rt, wo wir uns befinden, und was die n\u00e4chsten Schritte sind. \u00dcber Entscheidungsvorlagen k\u00f6nnen weitere Budgets oder Termine abgestimmt werden.<\/li>\n<\/ul>\n<p>Hilfreich ist es auch, Probleme und Teilerfolge im Team zu diskutieren. Dazu m\u00fcssen Vorgehen und Ergebnisse auch in entsprechender Form aufbereitet werden.<\/p>\n<h3><strong>Betriebskennzahlen ermitteln<\/strong><\/h3>\n<p><strong>Prozess und Speicher<\/strong><\/p>\n<p>Im <a title=\"Was tun bei OutOfMemory \u2013 Teil 1: Grundlagen\" href=\"http:\/\/marko-seifert.de\/blog\/?p=43\">Teil 1<\/a> wurde bereits dargestellt, dass die Gr\u00f6\u00dfe des maximalen Speichers f\u00fcr einen Prozess abh\u00e4ngig von dem Betriebssystem und der Hardware ist.<br \/>\nAnzeigen kann man den Speicher f\u00fcr einen Prozess unter Linux mit dem Kommando top.<\/p>\n<pre>top -p &lt;PID&gt;<\/pre>\n<p>Weiterhin kann auch festgestellt werden, wie viel Ressourcen \u00fcberhaupt noch zur Verf\u00fcgung stehen.<br \/>\nUm herauszufinden, wie viel Speicher ein Prozess maximal einnehmen kann, ben\u00f6tigt man die genaue Kernel-Version und die Spezifikation des Betriebssystems.<\/p>\n<pre>uname -r (Linux)<\/pre>\n<ul>\n<li><a href=\"http:\/\/www.redhat.com\/docs\/manuals\/enterprise\/RHEL-4-Manual\/release-notes\/as-x86\/\" target=\"_blank\">In Betriebssystemspezifikation nachlesen (z.B. bei RedHat) <\/a><\/li>\n<\/ul>\n<p><em>Red Hat Enterprise Linux 4 includes a kernel known as the hugemem kernel.<br \/>\nThis kernel supports a 4GB per-process user space (versus 3GB for the other kernels), and a 4GB direct kernel space. <\/em><\/p>\n<p><strong>Java-Speicherverlauf \u00fcberwachen<\/strong><\/p>\n<ul>\n<li>GC-Logging aktivieren<\/li>\n<\/ul>\n<pre>JAVA_VM_ARGS=\"$JAVA_VM_ARGS -verbose:gc -Xloggc:var\/logs\/gc.log \\\r\n   -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC \\\r\n   -XX:+PrintTenuringDistribution\"<\/pre>\n<ul>\n<li>Auswerten der Datei <code>var\/logs\/gc.log<\/code> mit dem Tool HPjtune<\/li>\n<\/ul>\n<p><a href=\"http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/gc-log.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone  wp-image-8\" title=\"gc-log\" src=\"http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/gc-log.png\" alt=\"\" width=\"921\" height=\"525\" srcset=\"http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/gc-log.png 921w, http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/gc-log-300x171.png 300w, http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/gc-log-500x285.png 500w\" sizes=\"auto, (max-width: 921px) 100vw, 921px\" \/><\/a><\/p>\n<ul>\n<li>Kurz vor OutOfMemorykann durch GC kaum noch Speicher freigegeben werde<\/li>\n<li>das Systen ist praktisch nur noch mit GC besch\u00e4ftigt<\/li>\n<\/ul>\n<p><strong>Tomcat-Monitoring<\/strong><br \/>\n\u00dcber die Tomcat-Manager-Seiten kann der Tomcat \u00fcberwacht werden. Daf\u00fcr muss ein Nutzer mit der Rolle <code>manager<\/code> in der Datei <code>tomcat-users.xml<\/code> existieren.<\/p>\n<pre>&lt;?xml version='1.0' encoding='utf-8'?&gt;\r\n&lt;tomcat-users&gt;\r\n...\r\n&lt;role rolename=\"admin\"\/&gt;\r\n&lt;role rolename=\"manager\"\/&gt;\r\n&lt;user username=\"admin\" password=\"admin\" roles=\"admin, manager\"\/&gt;\r\n...\r\n&lt;\/tomcat-users&gt;<\/pre>\n<p>Tomcat Monitoring URL: <a>http:\/\/HOST:PORT\/manager\/status?XML=true<\/a><\/p>\n<pre>&lt;?xml version=\"1.0\" encoding=\"utf-8\"?&gt;\r\n&lt;status&gt;\r\n&lt;jvm&gt;\r\n&lt;memory free='206.306.536' total='424.214.528' max='492.175.360'\/&gt;\r\n&lt;\/jvm&gt;\r\n...\r\n&lt;\/status&gt;<\/pre>\n<p>Grafisch ausgewertet werden k\u00f6nnen die Werte mit JMeter:<\/p>\n<p><a href=\"http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/jmeter2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-12\" title=\"jmeter2\" src=\"http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/jmeter2-1024x668.png\" alt=\"\" width=\"584\" height=\"380\" srcset=\"http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/jmeter2-1024x668.png 1024w, http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/jmeter2-300x195.png 300w, http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/jmeter2-459x300.png 459w, http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/jmeter2.png 1030w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><\/a><\/p>\n<p><strong>Speicherdumps auswerten<\/strong><\/p>\n<p>Oft findet man die Ursachen des Speicherproblems aber nur mit der Auswertung des Heapdumps. Zuerst muss man ein Heapdump erstellen. Es empfiehlt sich, den Heap f\u00fcr die Analyse nicht zu gro\u00df zu w\u00e4hlen. Eine Analyse eines 2 GB Dumps ist schon sehr schwierig.<\/p>\n<ul>\n<li>Histogramm\n<pre> $JAVA_HOME\/bin\/jmap -histo &lt;PID&gt; &gt; hist.txt<\/pre>\n<\/li>\n<li>Binary HeapDump (komplett)\n<pre>$JAVA_HOME\/bin\/jmap -heap:format=b &lt;PID&gt;<\/pre>\n<\/li>\n<\/ul>\n<ul>\n<li>Auswerten mit JHat (JDK 1.6)\n<pre>java -Xmx2048m -jar hat.jar ..\/java_pid27280.hprof\r\nStarted HTTP server on port 7000\r\n Reading from ..\/java_pid27280.hprof...\r\n Dump file created Tue Nov 20 14:22:07 CET 2007<\/pre>\n<p>die Auswertung kann dann webbasiert per Browser auf Port: 7000 erfolgen<\/li>\n<li>Auswerten mit dem SAP Memory Analyzer\n<ul>\n<li>kostenloses Tool zum Analysieren von gro\u00dfen Memory Dumps<\/li>\n<li>sehr schnelle (durch Indizierung)<\/li>\n<li>sehr gute Analysem\u00f6glichkeiten<\/li>\n<li>Bearbeitung gro\u00dfer Dumps<\/li>\n<li>als Eclipse Plugin oder eigenst\u00e4ndige Applikation (RPC-Framework)<\/li>\n<li>Artikel im JavaMagazin (11\/2007 S.105)<\/li>\n<li>Download: <a href=\"https:\/\/wiki.sdn.sap.com\/wiki\/display\/Java\/Java+Memory+Analysis\">https:\/\/wiki.sdn.sap.com\/wiki\/display\/Java\/Java+Memory+Analysis<\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><a href=\"http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/sap-mem1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-11\" title=\"sap-mem1\" src=\"http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/sap-mem1-1024x710.png\" alt=\"\" width=\"584\" height=\"404\" srcset=\"http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/sap-mem1-1024x710.png 1024w, http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/sap-mem1-300x208.png 300w, http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/sap-mem1-432x300.png 432w, http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/sap-mem1.png 1064w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/sap-mem2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-9\" title=\"sap-mem2\" src=\"http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/sap-mem2-1024x710.png\" alt=\"\" width=\"584\" height=\"404\" srcset=\"http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/sap-mem2-1024x710.png 1024w, http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/sap-mem2-300x208.png 300w, http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/sap-mem2-432x300.png 432w, http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/sap-mem2.png 1064w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><\/a><\/p>\n<p><a href=\"http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/sap-mem3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-10\" title=\"sap-mem3\" src=\"http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/sap-mem3-1024x710.png\" alt=\"\" width=\"584\" height=\"404\" srcset=\"http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/sap-mem3-1024x710.png 1024w, http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/sap-mem3-300x208.png 300w, http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/sap-mem3-432x300.png 432w, http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/sap-mem3.png 1064w\" sizes=\"auto, (max-width: 584px) 100vw, 584px\" \/><\/a><\/p>\n<p>Im gezeigten Beispiel war das Problem die Klasse BodyContentImpl des Tomcats (5) allerdings durch fehlerhafte Benutzung in einer eigenen Tag Library.<\/p>\n<h3><strong>Links<\/strong><\/h3>\n<ul>\n<li><a title=\"Was tun bei OutOfMemory \u2013 Teil 1: Grundlagen\" href=\"http:\/\/marko-seifert.de\/blog\/?p=43\">Was tun bei OutOfMemory \u2013 Teil 1: Grundlagen<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Nicht selten kommt es vor, dass Speicherprobleme erst im Wirkbetrieb auftreten. Die Gr\u00fcnde daf\u00fcr sind oft, dass das System nicht ausreichend oder gar nicht unter realen Lastbedingungen getestet wurde. Bei Systemen mit redaktionellen Inhalten (z. B. Content Management Systeme) ergibt sich aus der steigenden Anzahl der Inhalte in Verbindung mit Abh\u00e4ngigkeiten und Caching\u00a0 eine wachsende Belastung. In der Testphase sind diese Inhalte in der Komplexit\u00e4t und Masse meist noch nicht verf\u00fcgbar.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11,4],"tags":[6,7,8,9],"class_list":["post-36","post","type-post","status-publish","format-standard","hentry","category-development","category-java","tag-java","tag-jee","tag-jvm","tag-outofmemory"],"_links":{"self":[{"href":"http:\/\/marko-seifert.de\/blog\/index.php?rest_route=\/wp\/v2\/posts\/36","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/marko-seifert.de\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/marko-seifert.de\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/marko-seifert.de\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/marko-seifert.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=36"}],"version-history":[{"count":10,"href":"http:\/\/marko-seifert.de\/blog\/index.php?rest_route=\/wp\/v2\/posts\/36\/revisions"}],"predecessor-version":[{"id":70,"href":"http:\/\/marko-seifert.de\/blog\/index.php?rest_route=\/wp\/v2\/posts\/36\/revisions\/70"}],"wp:attachment":[{"href":"http:\/\/marko-seifert.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=36"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/marko-seifert.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=36"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/marko-seifert.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=36"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}