it-swarm.com.de

JBoss 7, Java.lang.OutOfMemoryError: PermGen-Speicherplatz

Ich habe diesen Fehler gefunden, bei dem die CPU-Auslastung an ihre Grenzen stößt und JBoss einen Neustart (Java.lang.OutOfMemoryError: PermGen space) benötigt. 

Ich habe eine Lösung für ältere JBoss-Version gefunden, um die MaxPermSize zu erhöhen. Ich denke, das gleiche gilt für JBoss7.

Welcher Wert wäre gut genug, um sich keinem Problem zu stellen? Gibt es eine Möglichkeit, sich dauerhaft von diesem Problem zu lösen (wie etwa ein anderes VM wie JRockit)?

25
MaVRoSCy

Da dies nach mehreren erneuten Bereitstellungen geschieht, klingt es so, als ob Sie auf ein Classloader-Leck gestoßen sind, eine übliche Art von Permgen-Leck .

Diese reizenden Bestien geschehen aufgrund normaler (nicht schwacher) Verweise von Objekten, die sich im Besitz des Containers befinden, auf Objekte, die Instanzen von Klassen sind, die vom Klassenladeprogramm der Anwendung geladen werden. Wenn diese Verweise bei der Bereitstellung von Deployments nicht gelöscht werden, gibt es immer noch eine starke Referenzkette zum Classloader der Anwendung. Daher kann es nicht GC-basiert und die geladenen Klassen können nicht freigegeben werden.

Eine häufige Ursache sind statische Auflistungen in Containerklassen, die nicht statische Verweise auf hinzugefügte Anwendungsklassen enthalten.

JBoss AS 7 enthält einige ziemlich starke Vorkehrungen in seinem Modulsystem, um das Auslaufen von Classloadern zu verhindern. Ich bin überrascht, dass Sie einen ausgelöst haben. Seit ich von Glassfish zu AS7 gewechselt bin, habe ich kein Classloader-Leck mehr gesehen.

Durch die Erhöhung von MaxPermSize gewinnen Sie etwas Zeit, aber das Problem wird nicht beseitigt. 

Sie müssen wirklich herausfinden, warum der Classloader undicht ist. Das macht "Spaß". Sie genießen Steuern, zeitweilige Fehler und das Reinigen der Dusche, richtig? Sehen Sie sich die Links im ersten Abschnitt für einige Blogs an, mit deren Hilfe Sie das Leck nachverfolgen können. Im Allgemeinen möchten Sie mit VisualVM und OQL Dig für Verweise auf Ihren App-Classloader verwenden oder einen Heap-Dump erstellen und jhat (Teil der JDK), um die Referenzen zu finden. In jedem Fall sollten Sie herausfinden, wo die starke Referenzkette vom App-Server zu Ihrem Classloader über Instanzen Ihrer App-Klassen liegt.

Alternativ kann es hilfreich sein, eine Kopie Ihrer App zu entnehmen und dann Teile davon zu entfernen, bis das Leck verschwunden ist. Sie können feststellen, ob es undichte Stellen gibt, indem Sie VisualVM oder eine andere Überwachung mit dem App-Server VM verbinden und beobachten, ob PermGen nach zwei oder mehr Bereitstellungs-/Rücknahmezyklen ansteigt. Automatisieren Sie die Bereitstellungs- und Rückgabezyklen. Die Ursache des Lecks auf einen kleinen Teil Ihrer App und/oder eine ihrer Abhängigkeiten eingrenzen und einen kleinen, in sich geschlossenen Testfall erstellen, den Sie dann als Fehlerbericht auf (a) JBoss AS 7 einreichen, da dies von AFAIK möglich ist bedeutet, dies zu verhindern und (b) der Täter, der die Referenz hält.

Wenn Sie die Ursache auf eine Abhängigkeit beschränken, die in Ihrem Implementierungsarchiv gebündelt ist, kann das Problem durch das Verschieben in ein JBoss AS 7-Modul behoben werden. Erstellen Sie ein JBoss-Modul dafür, implementieren Sie es im Verzeichnis modules von AS7 und fügen Sie Ihrer Bereitstellung eine Abhängigkeit davon über Ihren Manifest.MF oder einen jboss-deployment-structure.xml hinzu. Siehe Dokumentation zum AS7-Klassenlader .

Deshalb macht mich die Tatsache, dass das Projekt Jigsaw verschoben wurde, traurig. Java benötigt ein starkes Modulsystem, das diesen Schwachkopf loswird.

54
Craig Ringer

Der Parameter VM lautet:

-XX:MaxPermSize=256M

Machen Sie es nur so groß, dass Sie das Limit nicht erreichen.

Allgemein wird Perm-Gen-Speicher für Objekte verwendet, die Klassen und internen Strings zugeordnet sind. Sie sollten nicht ausgehen, wenn Sie nicht viele verschiedene Klassen verwenden.

8
Bohemian

Wir mussten genau das Gleiche tun und leider hat visualvm nicht viel für uns getan.

Am Ende verwendeten wir Eclipse-Matte, um den beim Absturz erzeugten Heap-Dump zu analysieren, und checkten dann den leak suspects-Bericht aus, der uns mitteilte, dass viele ModuleClassLoader-Instanzen durchgesickert waren.

Wenn Sie auf eine der Instanzen im Übersichtsregister klicken und dann merge shortest paths to GC roots + exclude weak references auswählen, haben wir unseren Schuldigen bekommen, der es nicht zulässt, dass diese ModuleClassLoader-Instanzen GC-fähig sind!

https://smalldata.tech/blog/2015/09/29/detecting-Java-permgen-memory-leak

4
Victor Parmar

Warum passiert es? 

Der "PermGen" -Fehler tritt auf, wenn die Java Virtual Machine nicht mehr auf .__ läuft. Gedächtnis in der permanenten Generation. Erinnern Sie sich daran, dass Java eine .__ hat. generationsmüllsammler, mit vier generationen: eden, jung, alt und dauerhaft. In der Eden-Generation sind Objekte sehr kurz lebte und Müllsammlung ist schnell und oft. Die junge Generation Besteht aus Objekten, die die Generation von Eden überlebt haben (oder wurden .__ zu jung gedrückt, da die Generation von Eden zum Zeitpunkt der Zuweisung voll war), ist die Speicherbereinigung in der jungen Generation weniger häufig, aber immer noch in regelmäßigen Abständen (vorausgesetzt, dass Ihre Anwendung tatsächlich etwas tut und Objekte ab und zu alle Objekte zuordnet). Die alte Generation, du hast es verstanden. Es beinhaltet Objekte, die die junge Generation überlebt haben oder heruntergedrückt wurden, Die Müllabfuhr ist noch seltener, kann aber trotzdem passieren. Und schließlich die permanente Generation. Dies ist für Objekte, die die Die virtuelle Maschine hat sich entschlossen, das ewige Leben zu unterstützen - und zwar genau der Kern des Problems. Objekte in der permanenten Generierung werden niemals Müll gesammelt; das ist unter normalen Umständen, wenn Der jvm wird mit normalen Befehlszeilenparametern gestartet. Na und Wenn Sie Ihre Webanwendung erneut bereitstellen, geschieht dies, wenn Ihre WAR-Datei wird entpackt und die Klassendateien in die jvm geladen. Und hier ist der Sache: fast immer in der permanenten Generation landen ... (genommen von: http://rlogiacco.blogspot.com/2009/02/jboss-and-permgen-outofmemoryerror.html )

Hier einige Ratschläge: 

verwenden Sie diese Parameter für Ihre JVM. Sie weisen den Garbage Collector an, seinen Algorithmus auch auf PermGen aufzurufen.

set Java_OPTS=-Xms512m -Xmx1024m 
-XX:PermSize=512m 
-XX:MaxPermSize=1024m 
-XX:+UseConcMarkSweepGC 
-XX:+CMSPermGenSweepingEnabled 
-XX:+CMSClassUnloadingEnabled 
  • Die Einstellung CMSPermGenSweepingEnabled enthält PermGen in einem Garbage Collection-Lauf. Standardmäßig ist der PermGen-Speicherplatz niemals in der Garbage Collection enthalten (und wächst daher ohne Grenzen).
  • Die Einstellung CMSClassUnloadingEnabled teilt dem PermGen-Garbage Collection-Sweep mit, dass er auf Klassenobjekte reagieren soll. Standardmäßig erhalten Objekte der Klasse .__ eine Ausnahme, selbst wenn der PermGen-Space während einer Garabage-Auflistung Besucht wird.

Starten Sie Ihr JBOSS neu, da Sie bei jeder Bereitstellung der Anwendung die Datenmenge im PermGen erhöhen. 

Sie können auch JRocket JVM anstelle von Sun JVM verwenden. Es hat kein PermGen in seinem Garbage Collector-Algorithmus. 

1
Kamal SABBAR