{"id":43,"date":"2012-06-27T09:18:03","date_gmt":"2012-06-27T07:18:03","guid":{"rendered":"http:\/\/marko-seifert.de\/blog\/?p=43"},"modified":"2020-01-15T12:23:37","modified_gmt":"2020-01-15T10:23:37","slug":"was-tun-bei-outofmemory-teil-1-grundlagen","status":"publish","type":"post","link":"http:\/\/marko-seifert.de\/blog\/?p=43","title":{"rendered":"Was tun bei OutOfMemory \u2013 Teil 1: Grundlagen"},"content":{"rendered":"<p><strong><em>OutOfMemory ist eines der am h\u00e4ufigsten auftretenden Probleme bei Java-basierten Webapplikationen. Die Ursachen daf\u00fcr sind genau so vielschichtig wie die M\u00f6glichkeiten der Analyse. Ziel dieses Artikels ist es, sowohl die Grundlagen wie auch m\u00f6gliche L\u00f6sungswege zu zeigen.<\/em><\/strong><\/p>\n<p>Bevor man jetzt leichtfertig die Software umprogrammiert (da man ja genau wei\u00df, wo das Problem liegt), sollte man mit einer ausf\u00fchrlichen Analyse beginnen. Nicht selten kommt es vor, dass Software (Parameter der JVM) oder sogar das Betriebssystem nicht korrekt konfiguriert sind.<!--more--><\/p>\n<h2>Die Process Size<\/h2>\n<p>Die Process Size ist der maximal verf\u00fcgbare Speicher f\u00fcr den Prozess. Dieser ist abh\u00e4ngig von der Hardware und vom Betriebssystem. In einer 32 Bit-Architektur kann die Process Size maximal 4 GB sein. F\u00fcr einen Java-Prozess gibt es folgende Bereiche, die im Speicher des Prozesses liegen (siehe Abbildung 1):<\/p>\n<ul>\n<li><em><strong>Java Heap <\/strong><\/em>&#8211; Der Heap ist der Speicher, in dem die Java Objekte erzeugt und verwaltet werden.<\/li>\n<li><em><strong>Permanent Generation<\/strong><\/em> \u2013 Die Permanent Generation ist der Speicher, in dem die JVM sich selber verwaltet. In diesem Speicher werden auch die Klassen durch den ClassLoader geladen.<\/li>\n<li><em><strong>Nativ Code<\/strong><\/em> \u2013 Jeder Java-Prozess ben\u00f6tigt auch Speicher f\u00fcr den Native Code. Das sind C-Bibliotheken des Betriebssystems f\u00fcr den Zugriff auf Systemressourcen. Zum Beispiel der Zugriff aufs Dateisystem.<\/li>\n<\/ul>\n<div id=\"attachment_20\" style=\"width: 260px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/processsize3.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-20\" class=\"size-full wp-image-20\" title=\"processsize3\" src=\"http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/processsize3.png\" alt=\"\" width=\"250\" height=\"160\" \/><\/a><p id=\"caption-attachment-20\" class=\"wp-caption-text\">Abbildung 1: Schematischer Aufbau der Speicherverteilung eines Java-Prozesses<\/p><\/div>\n<p>Der Speicher f\u00fcr den Native Code ist nicht explizit einstellbar. Er ergibt sich aus der Differenz zwischen Process Size, Heap und Permanent Generation. Dieser Speicher darf nicht zu knapp bemessen sein, denn es kann auch OutOfMemory im Native Code geben.<\/p>\n<h2>Die Java Heap Size<\/h2>\n<p>Die Java Heap Size gibt die Gr\u00f6\u00dfe des Speichers an, der f\u00fcr die Erzeugung und Verwaltung der Java-Objekte verwendet werden kann. Die Gr\u00f6\u00dfe des Heaps ist begrenzt. Wird keine Gr\u00f6\u00dfe explizit angegeben, wird die Defaulteinstellung verwendet. Diese variiert von Betriebssystem zu Betriebssystem. Wenn man wirklich sicher gehen m\u00f6chte, stellt man die Gr\u00f6\u00dfe explizit ein:<\/p>\n<p><strong><code>-Xms[Bytes]m<\/code><\/strong><\/p>\n<ol>\n<ol>: initiale Gr\u00f6\u00dfe des Heaps beim Starten des Prozesses<\/ol>\n<\/ol>\n<p><strong><code>-Xmx[Bytes]m<\/code><\/strong><\/p>\n<ol>: maximale Gr\u00f6\u00dfe des Heaps \u00fcber den gesamten Lebenszeitraum<\/ol>\n<p>Der Heap teilt sich in zwei gro\u00dfe Bereiche: der New Generation und der Old Generation (siehe Abbildung 2).<br \/>\nWie die Namen schon vermuten lassen, befinden sich in der New Generation die ganzen neuen, jungen und kurzlebigen Java-Objekte und in der Old Generation die langlebigen Java-Objekte.<\/p>\n<div id=\"attachment_19\" style=\"width: 330px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/heap.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-19\" class=\"size-full wp-image-19\" title=\"heap\" src=\"http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/heap.png\" alt=\"\" width=\"320\" height=\"220\" srcset=\"http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/heap.png 320w, http:\/\/marko-seifert.de\/blog\/wp-content\/uploads\/2012\/06\/heap-300x206.png 300w\" sizes=\"auto, (max-width: 320px) 100vw, 320px\" \/><\/a><p id=\"caption-attachment-19\" class=\"wp-caption-text\">Abbildung 2: Aufteilung der Speicherbereiche im Heap<\/p><\/div>\n<p>&nbsp;<\/p>\n<p>Das Verh\u00e4ltnis zwischen New und Old Generation ist aus Speichersicht der gr\u00f6\u00dfte Unterschied zwischen einer Desktop- und einer Serveranwendung. Eine Desktopanwendung l\u00e4uft in der Regel einen Arbeitstag, also ca. 8 h. Eine Serveranwendung l\u00e4uft 24 h, 7 Tage die Woche und das mehrere Monate. Daran kann man schon erkennen, dass es bei einer Desktopanwendung mehr j\u00fcngere Objekte und bei einer Serveranwendung mehr \u00e4ltere Objekte gibt. Mit dem Servermodus stellt man das Verh\u00e4ltnis zwischen New und Old Generation auf <strong>1:3<\/strong> ein.<\/p>\n<p><code>-server<\/code><\/p>\n<ol>:Servermodus f\u00fcr die VM<\/ol>\n<h3>Permanent Generation<\/h3>\n<p>Die Permanent Generation wird von der JVM f\u00fcr das Laden der Klassen durch den ClassLoader verwendet. Normalerweise ist die Defaulteinstellung der Gr\u00f6\u00dfe ausreichend. Wenn allerdings viele Klassen dynamisch durch die Applikation geladen werden (z.B. durch Reflection), kann die Defaulteinstellung zu Problemen f\u00fchren. Auch die Verwendung von Persistenz- oder Caching-Frameworks f\u00fchrt zu gr\u00f6\u00dferem Speicherverbrauch in der Permanent Generation.<br \/>\n\u00dcber folgende Parameter kann die Defaultgr\u00f6\u00dfe der Permanent Generation angepasst werden:<\/p>\n<p><code>-XX:PermSize=[Bytes]m :<\/code><\/p>\n<ol>\n<ol>initiale Gr\u00f6\u00dfe der Permanent Generation<\/ol>\n<\/ol>\n<p><code>-XX:MaxPermSize=[Bytes]m :<\/code><\/p>\n<ol>maximale Gr\u00f6\u00dfe der Permanent Generation<\/ol>\n<h2>Garbage Collection<\/h2>\n<p>Man unterscheidet bei der Garbage Collection in die (\u201eeinfache\u201c) Garbage Collection und in die Full Garbage Collection. Bei der Garbage Collection werden nicht mehr referenzierte Objekte aus der New Generation freigegeben. Des Weiteren werden noch \u201elebende\u201c Objekte, die durch mehrere Garbage Collection nicht freigegeben wurden, in die Old Generation kopiert. Bei einer Full Garbage Collection werden auch Objekte aus der Old Generation aufger\u00e4umt.<br \/>\nEine Full Garbage Collection ist sehr zeitintensiv (bei 2 GB Heap Size = mehrere Sekunden). W\u00e4hrend dieser Zeit reagiert die Applikation nicht mehr.<br \/>\nIst die Heap Size zu gering eingestellt, findet eine Full Garbage Collection nach der anderen statt. Dies f\u00fchrt zu einer sehr schlechten Performance und zu langen Antwortszeiten.<br \/>\nIn einer Multiprozessor-Maschine ist es deshalb ratsam, die Garbage Collection (\u201eeinfache\u201c und Full) parallel arbeiten zu lassen.<\/p>\n<p><code>-XX:+UseParallelGC: <\/code><\/p>\n<ol>parallele Garbage Collection und Full Garbage Collection<\/ol>\n<h3>Ausblick<\/h3>\n<p>Nachdem in diesem Artikel die Grundlagen erl\u00e4utert wurden, werden im n\u00e4chsten Artikel konkrete Analyse-M\u00f6glichkeiten besprochen.<\/p>\n<h3>Links<\/h3>\n<ul>\n<li><a title=\"View Systemanalyse von OutOfMemory Fehlern in Java-Anwendungen on SlideShare\" href=\"http:\/\/www.slideshare.net\/communardo\/systemanalyse-von-outofmemory-fehlern-in-javaanwendungen?src=embed\">Systemanalyse von OutOfMemory Fehlern in Java-Anwendungen<\/a><\/li>\n<li><a title=\"Was tun bei OutOfMemory \u2013 Teil 2: Analyse\" href=\"http:\/\/marko-seifert.de\/blog\/?p=36\">Was tun bei OutOfMemory \u2013 Teil 2: Analyse<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>OutOfMemory ist eines der am h\u00e4ufigsten auftretenden Probleme bei Java-basierten Webapplikationen. Die Ursachen daf\u00fcr sind genau so vielschichtig wie die M\u00f6glichkeiten der Analyse. Ziel dieses Artikels ist es, sowohl die Grundlagen wie auch m\u00f6gliche L\u00f6sungswege zu zeigen. Bevor man jetzt leichtfertig die Software umprogrammiert (da man ja genau wei\u00df, wo das Problem liegt), sollte man mit einer ausf\u00fchrlichen Analyse beginnen. Nicht selten kommt es vor, dass Software (Parameter der JVM) oder sogar das Betriebssystem nicht korrekt konfiguriert sind.<\/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-43","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\/43","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=43"}],"version-history":[{"count":9,"href":"http:\/\/marko-seifert.de\/blog\/index.php?rest_route=\/wp\/v2\/posts\/43\/revisions"}],"predecessor-version":[{"id":69,"href":"http:\/\/marko-seifert.de\/blog\/index.php?rest_route=\/wp\/v2\/posts\/43\/revisions\/69"}],"wp:attachment":[{"href":"http:\/\/marko-seifert.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=43"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/marko-seifert.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=43"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/marko-seifert.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=43"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}