Vor kurzem bin ich in meiner Webanwendung auf diesen Fehler gestoßen:
java.lang.OutOfMemoryError: PermGen-Speicherplatz
Es ist eine typische Hibernate / JPA + IceFaces / JSF-Anwendung, die unter Tomcat 6 und JDK 1.6 ausgeführt wird. Anscheinend kann dies nach mehrmaliger erneuter Bereitstellung einer Anwendung auftreten.
Was verursacht es und was kann getan werden, um es zu vermeiden? Wie behebe ich das Problem?
Antworten:
Die Lösung bestand darin, diese Flags der JVM-Befehlszeile hinzuzufügen, wenn Tomcat gestartet wird:
Sie können dies tun, indem Sie den Tomcat-Dienst herunterfahren, dann in das Tomcat / bin-Verzeichnis wechseln und tomcat6w.exe ausführen. Fügen Sie auf der Registerkarte "Java" die Argumente zum Feld "Java-Optionen" hinzu. Klicken Sie auf "OK" und starten Sie den Dienst neu.
Wenn Sie eine Fehlermeldung erhalten, existiert der angegebene Dienst nicht als installierter Dienst, den Sie ausführen sollten:
Dabei ist Servicename der Name des Servers in der Datei services.msc
Quelle: Orxs Kommentar zu Eric's Agile Answers .
quelle
Versuchen Sie es
-XX:MaxPermSize=128M
lieber als-XX:MaxPermGen=128M
.Ich kann die genaue Verwendung dieses Speicherpools nicht sagen, aber es hängt mit der Anzahl der in die JVM geladenen Klassen zusammen. (Durch Aktivieren des Entladens von Klassen für Tomcat kann das Problem behoben werden.) Wenn Ihre Anwendungen beim Ausführen Klassen generieren und kompilieren, ist es wahrscheinlicher, dass ein Speicherpool benötigt wird, der größer als der Standard ist.
quelle
PermGen-Fehler des App-Servers, die nach mehreren Bereitstellungen auftreten, werden höchstwahrscheinlich durch Verweise verursacht, die der Container in den Klassenladeprogrammen Ihrer alten Apps enthält. Wenn Sie beispielsweise eine benutzerdefinierte Klasse auf Protokollebene verwenden, werden Referenzen vom Klassenladeprogramm des App-Servers gespeichert. Sie können diese Lecks zwischen Klassenladern erkennen, indem Sie moderne (JDK6 +) JVM-Analysetools wie jmap und jhat verwenden, um zu überprüfen, welche Klassen weiterhin in Ihrer App enthalten sind, und ihre Verwendung neu zu gestalten oder zu beseitigen. Übliche Verdächtige sind Datenbanken, Logger und andere Bibliotheken auf Basis-Framework-Ebene.
Siehe Classloader-Lecks: Die gefürchtete Ausnahme "java.lang.OutOfMemoryError: PermGen space" und insbesondere der nachfolgende Beitrag .
quelle
Häufige Fehler, die Menschen machen, sind der Gedanke, dass Heap Space und Permgen Space gleich sind, was überhaupt nicht stimmt. Sie könnten noch viel Speicherplatz auf dem Heap haben, aber in permgen kann immer noch nicht genügend Speicherplatz vorhanden sein.
Häufige Ursachen für OutofMemory in PermGen sind ClassLoader. Wenn eine Klasse in JVM geladen wird, werden alle ihre Metadaten zusammen mit Classloader im PermGen-Bereich gespeichert und sie werden mit Müll gesammelt, wenn der Classloader, der sie geladen hat, für die Garbage Collection bereit ist. In dem Fall, dass Classloader einen Speicherverlust aufweist, bleiben alle von ihm geladenen Klassen im Speicher und verursachen PermGen outofmemory, sobald Sie ihn einige Male wiederholen. Das klassische Beispiel ist Java.lang.OutOfMemoryError: PermGen Space in Tomcat .
Nun gibt es zwei Möglichkeiten, dies zu lösen:
1. Finden Sie die Ursache für einen Speicherverlust oder wenn ein Speicherverlust vorliegt.
2. Erhöhen Sie die Größe von PermGen Space mithilfe von JVM param
-XX:MaxPermSize
und-XX:PermSize
.Sie können auch 2 Lösung von Java.lang.OutOfMemoryError in Java für weitere Details überprüfen .
quelle
-XX:MaxPermSize and -XX:PermSize
? Ich kann nicht findencatalina.bat
. Meine Tomcat-Version ist5.5.26
.Verwenden Sie den Befehlszeilenparameter
-XX:MaxPermSize=128m
für eine Sun-JVM (ersetzen Sie offensichtlich 128 durch die gewünschte Größe).quelle
Versuchen Sie
-XX:MaxPermSize=256m
es und versuchen Sie es, wenn es weiterhin besteht-XX:MaxPermSize=512m
quelle
XX:MaxPermSize=1024m
:)Ich fügte hinzu
-XX: MaxPermSize = 128m
VM-Argumente (Sie können experimentieren, was am besten funktioniert), da ich eclipse ide verwende. In den meisten JVM- Versionen beträgt die Standard-PermSize etwa 64 MB , wenn nicht genügend Speicher vorhanden ist, wenn das Projekt zu viele Klassen oder eine große Anzahl von Zeichenfolgen enthält.Für Eclipse wird es auch bei der Antwort beschrieben .
SCHRITT 1 : Doppelklicken Sie auf den Tomcatbediener auf Servern Tab
SCHRITT 2 : Öffnen Sie Launch Conf und fügen Sie
-XX: MaxPermSize = 128m
am Ende vorhandene VM-Argumente hinzu .quelle
Ich habe mich beim Bereitstellen und Aufheben der Bereitstellung einer komplexen Webanwendung mit diesem Problem auseinandergesetzt und dachte, ich würde eine Erklärung und meine Lösung hinzufügen.
Wenn ich eine Anwendung auf Apache Tomcat bereitstelle, wird ein neuer ClassLoader für diese App erstellt. Der ClassLoader wird dann verwendet, um alle Klassen der Anwendung zu laden, und beim Aufheben der Bereitstellung sollte alles gut gehen. In Wirklichkeit ist es jedoch nicht ganz so einfach.
Eine oder mehrere der Klassen, die während der Lebensdauer der Webanwendung erstellt wurden, enthalten eine statische Referenz, die irgendwo entlang der Linie auf den ClassLoader verweist. Da die Referenz ursprünglich statisch ist, wird diese Referenz durch keine Speicherbereinigung bereinigt. Der ClassLoader und alle geladenen Klassen bleiben erhalten.
Und nach ein paar Neueinsätzen stoßen wir auf den OutOfMemoryError.
Nun ist dies ein ziemlich ernstes Problem geworden. Ich könnte sicherstellen, dass Tomcat nach jeder erneuten Bereitstellung neu gestartet wird, aber dadurch wird der gesamte Server heruntergefahren und nicht nur die neu bereitgestellte Anwendung, was häufig nicht möglich ist.
Also habe ich stattdessen eine Lösung in Code zusammengestellt, die unter Apache Tomcat 6.0 funktioniert. Ich habe auf keinem anderen Anwendungsserver getestet und muss betonen, dass dies ohne Änderungen auf einem anderen Anwendungsserver sehr wahrscheinlich nicht funktioniert .
Ich möchte auch sagen, dass ich diesen Code persönlich hasse und dass niemand dies als "schnelle Lösung" verwenden sollte, wenn der vorhandene Code geändert werden kann, um die richtigen Methoden zum Herunterfahren und Bereinigen zu verwenden . Dies sollte nur verwendet werden, wenn es eine externe Bibliothek gibt, von der Ihr Code abhängig ist (in meinem Fall war es ein RADIUS-Client), die keine Möglichkeit bietet, seine eigenen statischen Referenzen zu bereinigen.
Wie auch immer, weiter mit dem Code. Dies sollte an dem Punkt aufgerufen werden, an dem die Anwendung nicht bereitgestellt wird, z. B. die Zerstörungsmethode eines Servlets oder (der bessere Ansatz) die contextDestroyed-Methode eines ServletContextListener.
quelle
Die
java.lang.OutOfMemoryError: PermGen
Leertaste zeigt an, dass der Speicherbereich der permanenten Generation erschöpft ist.Alle Java-Anwendungen dürfen nur eine begrenzte Menge an Speicher verwenden. Die genaue Speichermenge, die Ihre bestimmte Anwendung verwenden kann, wird beim Start der Anwendung angegeben.
Der Java-Speicher ist in verschiedene Regionen unterteilt, die im folgenden Bild zu sehen sind:
Metaspace: Ein neuer Erinnerungsraum wird geboren
Die JDK 8 HotSpot-JVM verwendet jetzt nativen Speicher für die Darstellung von Klassenmetadaten und heißt Metaspace. ähnlich den Oracle JRockit- und IBM JVMs.
Die gute Nachricht ist, dass Sie keine
java.lang.OutOfMemoryError: PermGen
Speicherplatzprobleme mehr haben und diesen Speicherplatz nicht mehr mit Java_8_Download oder höher optimieren und überwachen müssen .quelle
1) Erhöhen der PermGen-Speichergröße
Das erste, was man tun kann, ist, den Heap-Speicher der permanenten Generation zu vergrößern. Dies ist mit den üblichen JVM-Argumenten –Xms (anfängliche Heap-Größe festlegen) und –Xmx (maximale Heap-Größe festlegen) nicht möglich, da der Heap-Speicher der permanenten Generierung wie erwähnt vollständig vom regulären Java-Heap-Speicher getrennt ist und diese Argumente festgelegt sind Der Speicherplatz für diesen regulären Java-Heapspeicher. Es gibt jedoch ähnliche Argumente, die verwendet werden können (zumindest mit den Sun / OpenJDK-JVMS), um die Größe des permanenten Generierungshaufens zu vergrößern:
Standard ist 64m.
2) Aktivieren Sie das Kehren
Eine andere Möglichkeit, dies endgültig zu erledigen, besteht darin, das Entladen von Klassen zuzulassen, damit Ihr PermGen nie ausgeht:
Solche Sachen haben in der Vergangenheit für mich Magie gewirkt. Eine Sache ist jedoch, dass die Verwendung dieser Produkte einen erheblichen Leistungskompromiss darstellt, da Permgen-Sweeps für jede von Ihnen gestellte Anfrage oder etwas in dieser Richtung zusätzliche 2 Anfragen stellen. Sie müssen Ihre Verwendung mit den Kompromissen in Einklang bringen.
Sie können die Details dieses Fehlers finden.
http://faisalbhagat.blogspot.com/2014/09/java-outofmemoryerror-permgen.html
quelle
Alternativ können Sie zu JRockit wechseln, das das Permgen anders handhabt als das JVM von Sun. Es hat im Allgemeinen auch eine bessere Leistung.
http://www.oracle.com/technetwork/middleware/jrockit/overview/index.html
quelle
java.lang.OutOfMemoryError: There is insufficient native memory
stattdessen bekommen .Ich hatte das Problem, über das wir hier sprechen. Mein Szenario ist Eclipse-Helios + Tomcat + JSF. Sie haben eine einfache Anwendung für Tomcat bereitgestellt. Ich habe hier das gleiche Problem gezeigt und es wie folgt gelöst.
In Eclipse gehen Sie zur Registerkarte Server. Doppelklicken Sie in meinem Fall auf den registrierten Server. Tomcat 7.0 öffnet meinen Dateiserver. Allgemeine Registrierungsinformationen. Klicken Sie im Abschnitt "Allgemeine Informationen" auf den Link "Startkonfiguration öffnen" . Dadurch wird die Ausführung von Serveroptionen auf der Registerkarte "Argumente" in VM-Argumenten geöffnet, die am Ende dieser beiden Einträge hinzugefügt wurden
und fertig.
quelle
Die einfachste Antwort ist heutzutage die Verwendung von Java 8.
Es reserviert nicht mehr ausschließlich Speicher für PermGen-Speicherplatz, sodass sich der PermGen-Speicher mit dem regulären Speicherpool vermischen kann.
Beachten Sie, dass Sie alle nicht standardmäßigen
-XXPermGen...=...
JVM-Startparameter entfernen müssen, wenn Sie nicht möchten, dass Java 8 sich darüber beschwert, dass sie nichts tun.quelle
Fügen Sie im Textbereich Java-Optionen diese Zeile hinzu:
quelle
Ein Fehler im Perm-Speicherplatz tritt aufgrund der Verwendung eines großen Speicherplatzes auf, anstatt dass jvm Speicherplatz für die Ausführung des Codes bereitstellt.
Die beste Lösung für dieses Problem unter UNIX-Betriebssystemen besteht darin, einige Konfigurationen in der Bash-Datei zu ändern. Die folgenden Schritte lösen das Problem.
Führen Sie den Befehl
gedit .bashrc
auf dem Terminal aus.Erstellen Sie eine
JAVA_OTPS
Variable mit folgendem Wert:Speichern Sie die Bash-Datei. Führen Sie den Befehl exec bash auf dem Terminal aus. Starten Sie den Server neu.
Ich hoffe, dieser Ansatz wird bei Ihrem Problem funktionieren. Wenn Sie eine Java-Version unter 8 verwenden, tritt dieses Problem manchmal auf. Wenn Sie jedoch Java 8 verwenden, tritt das Problem nie auf.
quelle
Das Erhöhen der Größe der permanenten Generierung oder das Ändern der GC-Parameter hilft NICHT, wenn Sie einen echten Speicherverlust haben. Wenn Ihre Anwendung oder eine Bibliothek eines Drittanbieters verwendet wird, besteht die einzige echte und dauerhafte Lösung darin, dieses Leck zu finden und zu beheben. Es gibt eine Reihe von Tools, die Ihnen helfen können. Eines der jüngsten ist Plumbr , das gerade eine neue Version mit den erforderlichen Funktionen veröffentlicht hat.
quelle
Wenn Sie log4j in Ihrer Webanwendung verwenden, überprüfen Sie diesen Absatz in der log4j- Dokumentation .
Es scheint, dass Sie bei der Verwendung
PropertyConfigurator.configureAndWatch("log4j.properties")
Speicherverluste verursachen, wenn Sie die Bereitstellung Ihrer Webanwendung aufheben.quelle
Ich habe eine Kombination von Hibernate + Eclipse RCP, versucht , mit
-XX:MaxPermSize=512m
und-XX:PermSize=512m
und es scheint , für mich zu arbeiten.quelle
Stellen Sie ein
-XX:PermSize=64m -XX:MaxPermSize=128m
. Später können Sie auch versuchen, zu erhöhenMaxPermSize
. Hoffe es wird funktionieren. Das gleiche funktioniert bei mir. Das EinstellenMaxPermSize
hat bei mir nicht funktioniert.quelle
Ich habe mehrere Antworten ausprobiert und das einzige, was den Job letztendlich erledigt hat, war diese Konfiguration für das Compiler-Plugin im POM:
hoffe dieser hilft.
quelle
Jrockitlöste dies auch für mich auf; Ich bemerkte jedoch, dass die Servlet-Neustartzeiten viel schlechter waren. Während es in der Produktion besser war, war es eine Art Entwicklungsproblem.
quelle
Die Konfiguration des Speichers hängt von der Art Ihrer App ab.
Was machst du gerade?
Wie viele Transaktionen wurden ausgeführt?
Wie viele Daten laden Sie?
usw.
usw.
usw
Wahrscheinlich könnten Sie Ihre App profilieren und einige Module aus Ihrer App bereinigen.
Tomcat verfügt über eine Hot-Bereitstellung, verbraucht jedoch Speicher. Starten Sie Ihren Container von Zeit zu Zeit neu. Außerdem müssen Sie wissen, wie viel Speicher für die Ausführung im Produktionsmodus erforderlich ist. Dies scheint ein guter Zeitpunkt für diese Recherche zu sein.
quelle
Sie sagen, dass die neueste Version von Tomcat (6.0.28 oder 6.0.29) die Aufgabe der erneuten Bereitstellung von Servlets viel besser erledigt .
quelle
Ich habe genau das gleiche Problem, aber leider hat keine der vorgeschlagenen Lösungen wirklich für mich funktioniert. Das Problem trat während der Bereitstellung nicht auf, und ich führte auch keine Hot-Bereitstellungen durch.
In meinem Fall trat das Problem jedes Mal zum gleichen Zeitpunkt während der Ausführung meiner Webanwendung auf, während eine Verbindung (über den Ruhezustand) zur Datenbank hergestellt wurde.
Dieser Link (ebenfalls zuvor erwähnt) lieferte genügend Insider-Informationen, um das Problem zu beheben. Das Verschieben des jdbc- (mysql) -Treibers aus dem WEB-INF in den Ordner jre / lib / ext / scheint das Problem gelöst zu haben. Dies ist nicht die ideale Lösung, da Sie für ein Upgrade auf eine neuere JRE den Treiber neu installieren müssen. Ein weiterer Kandidat, der ähnliche Probleme verursachen könnte, ist log4j. Vielleicht möchten Sie auch diesen verschieben
quelle
Der erste Schritt in einem solchen Fall besteht darin, zu überprüfen, ob der GC Klassen aus PermGen entladen darf. Die Standard-JVM ist in dieser Hinsicht eher konservativ - Klassen werden geboren, um für immer zu leben. Nach dem Laden bleiben die Klassen im Speicher, auch wenn sie von keinem Code mehr verwendet werden. Dies kann zu einem Problem werden, wenn die Anwendung viele Klassen dynamisch erstellt und die generierten Klassen für längere Zeiträume nicht benötigt werden. In einem solchen Fall kann es hilfreich sein, der JVM das Entladen von Klassendefinitionen zu ermöglichen. Dies kann erreicht werden, indem Sie Ihren Startskripten nur einen Konfigurationsparameter hinzufügen:
Standardmäßig ist dies auf false gesetzt. Um dies zu aktivieren, müssen Sie die folgende Option in Java-Optionen explizit festlegen. Wenn Sie CMSClassUnloadingEnabled aktivieren, durchsucht GC auch PermGen und entfernt Klassen, die nicht mehr verwendet werden. Beachten Sie, dass diese Option nur funktioniert, wenn UseConcMarkSweepGC auch mit der folgenden Option aktiviert ist. Wenn Sie also ParallelGC oder, Gott bewahre, Serial GC ausführen, stellen Sie sicher, dass Sie Ihren GC auf CMS eingestellt haben, indem Sie Folgendes angeben:
quelle
Das Zuweisen von mehr Speicher für Tomcat ist NICHT die richtige Lösung.
Die richtige Lösung besteht darin, eine Bereinigung durchzuführen, nachdem der Kontext zerstört und neu erstellt wurde (die Hot-Bereitstellung). Die Lösung besteht darin, die Speicherlecks zu stoppen.
Wenn Ihr Tomcat / Webapp-Server Ihnen mitteilt, dass die Registrierung von Treibern (JDBC) fehlgeschlagen ist, heben Sie die Registrierung auf. Dadurch werden Speicherlecks gestoppt.
Sie können einen ServletContextListener erstellen und in Ihrer web.xml konfigurieren. Hier ist ein Beispiel für einen ServletContextListener:
Und hier konfigurieren Sie es in Ihrer web.xml:
quelle
"Sie" sind falsch, weil ich 6.0.29 verwende und das gleiche Problem habe, auch nachdem ich alle Optionen festgelegt habe. Wie Tim Howland oben sagte, haben diese Optionen nur das Unvermeidliche aufgeschoben. Sie ermöglichen es mir, dreimal neu bereitzustellen, bevor der Fehler auftritt, anstatt jedes Mal, wenn ich erneut bereitstelle.
quelle
Falls Sie dies in der Eclipse IDE bekommen, auch nach der Einstellung der Parameter
--launcher.XXMaxPermSize
,-XX:MaxPermSize
etc., immer noch , wenn Sie die gleiche Fehlermeldung erhalten, ist es sehr wahrscheinlich ist , dass die Eklipse eine fehlerhafte Version von JRE verwendet , die von einigen installiert worden wäre , Anwendungen von Drittanbietern und auf Standard gesetzt. Diese fehlerhaften Versionen übernehmen die PermSize-Parameter nicht und unabhängig von Ihrer Einstellung werden diese Speicherfehler immer wieder angezeigt. Fügen Sie also in Ihrer eclipse.ini die folgenden Parameter hinzu:Stellen Sie außerdem sicher, dass Sie die Standard-JRE in den Einstellungen in der Eclipse auf die richtige Version von Java einstellen.
quelle
Der einzige Weg, der für mich funktionierte, war mit der JRockit JVM. Ich habe MyEclipse 8.6.
Der Heap der JVM speichert alle Objekte, die von einem laufenden Java-Programm generiert wurden. Java verwendet den
new
Operator zum Erstellen von Objekten, und der Speicher für neue Objekte wird zur Laufzeit auf dem Heap zugewiesen. Die Speicherbereinigung ist der Mechanismus zum automatischen Freigeben des Speichers der Objekte, auf die das Programm nicht mehr verweist.quelle
Ich hatte ein ähnliches Problem. Meins ist JDK 7 + Maven 3.0.2 + Struts 2.0 + Google GUICE-Projekt auf Basis der Abhängigkeitsinjektion.
Wann immer ich versuchte, den
mvn clean package
Befehl auszuführen , wurde der folgende Fehler angezeigt und "BUILD FAILURE" trat aufIch habe alle oben genannten nützlichen Tipps und Tricks ausprobiert, aber leider hat keiner für mich funktioniert. Was für mich funktioniert hat, wird Schritt für Schritt beschrieben: =>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
Element und dann ein<argLine>
Unterelement hinzu, in dem-Xmx512m -XX:MaxPermSize=256m
wie unten gezeigt übergeben wird =><configuration> <argLine>-Xmx512m -XX:MaxPermSize=256m</argLine> </configuration>
Hoffe es hilft, viel Spaß beim Programmieren :)
quelle