Frage

Ich schreibe eine Client-Seite Schwingen Anwendung (grafischer Schriftdesigner) auf Java 5.Vor kurzem stoße ich auf java.lang.OutOfMemoryError: Java heap space Fehler, weil ich bei der Speichernutzung nicht konservativ vorgehe.Der Benutzer kann eine unbegrenzte Anzahl von Dateien öffnen und das Programm behält die geöffneten Objekte im Speicher.Nach kurzer Recherche habe ich es gefunden Ergonomie in der Java Virtual Machine 5.0 und andere sagen, dass die JVM auf Windows-Rechnern standardmäßig die maximale Heap-Größe als einstellt 64MB.

Wie soll ich angesichts dieser Situation mit dieser Einschränkung umgehen?

Ich könnte das erhöhen maximale Heap-Größe verwenden Befehlszeile Option zu Java, aber das würde erfordern, den verfügbaren RAM herauszufinden und ein Startprogramm oder Skript zu schreiben.Außerdem steigt es auf einige endlich Max nicht letzten Endes Beseitigen Sie das Problem.

Ich könnte einen Teil meines Codes umschreiben, um Objekte häufig im Dateisystem zu speichern (die Verwendung einer Datenbank ist dasselbe), um Speicher freizugeben.Es könnte funktionieren, aber es ist wahrscheinlich auch eine Menge Arbeit.

Wenn Sie mich auf Details der oben genannten Ideen oder einige Alternativen hinweisen könnten, z Automatischer virtueller Speicher, der die Heap-Größe dynamisch erweitert, das wird toll.

War es hilfreich?

Lösung

Letztlich steht Ihnen immer eine begrenzte maximale Menge an Heap zur Verfügung, unabhängig davon, auf welcher Plattform Sie arbeiten.Unter Windows 32 Bit ist dies der Fall 2GB (nicht speziell Heap, sondern Gesamtspeichermenge pro Prozess).Es kommt einfach vor, dass Java sich dafür entscheidet, den Standardwert zu verkleinern (vermutlich, damit der Programmierer keine Programme mit unkontrollierter Speicherzuweisung erstellen kann, ohne auf dieses Problem zu stoßen und genau untersuchen zu müssen, was sie tun).

Vor diesem Hintergrund gibt es mehrere Ansätze, mit denen Sie entweder bestimmen können, wie viel Speicher Sie benötigen, oder um die von Ihnen verwendete Speichermenge zu reduzieren.Ein häufiger Fehler bei Garbage-Collected-Sprachen wie Java oder C# besteht darin, Verweise auf von Ihnen verwendete Objekte beizubehalten nicht mehr verwenden oder viele Objekte zuweisen, wenn Sie könnten Wiederverwendung sie stattdessen.Solange Objekte einen Verweis auf sie haben, belegen sie weiterhin Heap-Speicherplatz, da der Garbage Collector sie nicht löscht.

In diesem Fall können Sie einen Java-Speicherprofiler verwenden, um zu ermitteln, welche Methoden in Ihrem Programm eine große Anzahl von Objekten zuordnen, und dann feststellen, ob es eine Möglichkeit gibt, sicherzustellen, dass sie nicht mehr referenziert werden, oder sie überhaupt nicht zuzuweisen.Eine Option, die ich in der Vergangenheit verwendet habe, ist „JMP“. http://www.khelekore.org/jmp/.

Wenn Sie feststellen, dass Sie diese Objekte aus einem bestimmten Grund zuweisen und Referenzen beibehalten müssen (je nachdem, was Sie tun, kann dies der Fall sein), müssen Sie beim Starten des Programms lediglich die maximale Heap-Größe erhöhen.Sobald Sie jedoch die Speicherprofilierung durchgeführt und verstanden haben, wie Ihre Objekte zugewiesen werden, sollten Sie eine bessere Vorstellung davon haben, wie viel Speicher Sie benötigen.

Wenn Sie nicht garantieren können, dass Ihr Programm in einer begrenzten Speichermenge ausgeführt wird (vielleicht abhängig von der Eingabegröße), wird dieses Problem im Allgemeinen immer auftreten.Erst wenn dies alles ausgeschöpft ist, müssen Sie sich mit dem Zwischenspeichern von Objekten auf der Festplatte usw. befassen.An diesem Punkt sollten Sie einen sehr guten Grund haben, zu sagen: „Ich benötige XGB Speicher“ für etwas, und Sie können dies nicht umgehen, indem Sie Ihre Algorithmen oder Speicherzuweisungsmuster verbessern.Im Allgemeinen ist dies nur bei Algorithmen der Fall, die mit großen Datensätzen (wie einer Datenbank oder einem wissenschaftlichen Analyseprogramm) arbeiten, und dann werden Techniken wie Caching und speicherzugeordnete E/A nützlich.

Andere Tipps

Führen Sie Java mit der Befehlszeilenoption aus -Xmx, wodurch die festgelegt wird maximal Größe des Heaps.

Weitere Informationen finden Sie hier.

Sie könnten angeben pro Projizieren Sie, wie viel Heap-Speicherplatz Ihr Projekt benötigt

Das Folgende ist für Sonnenfinsternis Helios/Juno/Kepler:

Klicken Sie mit der rechten Maustaste auf

 Run As - Run Configuration - Arguments - Vm Arguments, 

dann füge das hinzu

-Xmx2048m

Das Erhöhen der Heap-Größe ist keine „Lösung“, sondern ein „Pflaster“, der zu 100 % vorübergehend ist.Es wird irgendwo anders wieder abstürzen.Um diese Probleme zu vermeiden, schreiben Sie Hochleistungscode.

  1. Verwenden Sie nach Möglichkeit lokale Variablen.
  2. Stellen Sie sicher, dass Sie das richtige Objekt auswählen (Bsp.:Auswahl zwischen String, StringBuffer und StringBuilder)
  3. Verwenden Sie ein gutes Codesystem für Ihr Programm (Bsp.:Verwendung statischer Variablen im Vergleich zu nicht statischen Variablen)
  4. Andere Dinge, die an Ihrem Code funktionieren könnten.
  5. Versuchen Sie, sich mit mehreren Fäden zu bewegen

Großer Vorbehalt: In meinem Büro stellten wir fest, dass wir (auf einigen Windows-Rechnern) nicht mehr als 512 m für den Java-Heap zuweisen konnten.Es stellte sich heraus, dass dies auf das auf einigen dieser Computer installierte Antivirenprodukt von Kaspersky zurückzuführen war.Nach der Deinstallation dieses AV-Produkts stellten wir fest, dass wir mindestens 1,6 GB zuweisen konnten, d. h. -Xmx1600m (m ist obligatorisch, sonst führt es zu einem weiteren Fehler „Zu kleiner anfänglicher Heap“) funktioniert.

Keine Ahnung, ob dies bei anderen AV-Produkten der Fall ist, aber vermutlich geschieht dies, weil das AV-Programm in jedem Adressraum einen kleinen Speicherblock reserviert und so eine einzelne wirklich große Zuweisung verhindert.

VM-Argumente haben bei mir in Eclipse funktioniert.Wenn Sie Eclipse Version 3.4 verwenden, gehen Sie wie folgt vor

gehe zu Run --> Run Configurations --> Wählen Sie dann das Projekt unter Maven Build aus -> wählen Sie dann die Registerkarte "JRE" -> und geben Sie dann ein -Xmx1024m.

Alternativ könnten Sie es tun Run --> Run Configurations --> select the "JRE" tab --> dann geben Sie ein -Xmx1024m

Dies sollte den Speicherheap für alle Builds/Projekte erhöhen.Die oben genannte Speichergröße beträgt 1 GB.Sie können nach Ihren Wünschen optimieren.

Ja, mit -Xmx Sie können mehr Speicher für Ihre JVM konfigurieren.Um sicherzustellen, dass kein Speicher verloren geht oder verschwendet wird.Nehmen Sie einen Heap-Dump und verwenden Sie ihn der Eclipse Memory Analyzer um Ihren Speicherverbrauch zu analysieren.

Ich möchte Empfehlungen von Oracle hinzufügen Fehlerbehebung Artikel.

Ausnahme im Thread Threadname: java.lang.OutOfMemoryError:Java heap space

Die detaillierte Meldung „Java-Heap-Speicherplatz“ weist darauf hin, dass das Objekt im Java-Heap nicht zugewiesen werden konnte.Dieser Fehler bedeutet nicht unbedingt einen Speicherverlust

Mögliche Ursachen:

  1. Einfaches Konfigurationsproblem, wobei die angegebene Heap-Größe für die Anwendung nicht ausreicht.

  2. Die Anwendung enthält unbeabsichtigt Verweise auf Objekte, und dies verhindert, dass die Objekte in den Müll gesammelt werden.

  3. Übermäßiger Einsatz von Finalizern.

Eine weitere mögliche Ursache für diesen Fehler entsteht bei Anwendungen, die übermäßig viele Finalizer verwenden.Wenn eine Klasse über eine Finalize-Methode verfügt, wird der Speicherplatz von Objekten dieses Typs zum Zeitpunkt der Garbage Collection nicht zurückgewonnen

Nach Müllabfuhr, die Objekte werden in die Warteschlange gestellt Finalisierung, was zu einem späteren Zeitpunkt erfolgt. Finalisierer werden von einem Daemon-Thread ausgeführt, der die Finalisierungswarteschlange bedient.Wenn die Finalisierer Wenn der Thread nicht mit der Finalisierungswarteschlange mithalten kann, könnte sich der Java-Heap füllen und so etwas passieren Außerhalb des Speicherfehler Es würde eine Ausnahme ausgelöst werden.

Ein Szenario, das diese Situation verursachen kann, ist die Erstellung einer Anwendung Threads mit hoher Priorität das verursacht das Finalisierung Die Warteschlange soll mit einer Geschwindigkeit anwachsen, die schneller ist als die Geschwindigkeit, mit der der Finalizer-Thread diese Warteschlange bedient.

Befolgen Sie die folgenden Schritte:

  1. Offen catalina.sh von Tomcat/bin.

  2. Ändern Sie JAVA_OPTS in

    JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1536m 
    -Xmx1536m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m 
    -XX:MaxPermSize=256m -XX:+DisableExplicitGC"
    
  3. Starten Sie Ihren Tomcat neu

Einfache Lösung OutOfMemoryError in Java besteht darin, die maximale Heap-Größe mithilfe von JVM-Optionen zu erhöhen -Xmx512M, dadurch wird Ihr OutOfMemoryError sofort behoben.Dies ist meine bevorzugte Lösung, wenn ich beim Erstellen eines Projekts in Eclipse, Maven oder ANT den Fehler „OutOfMemoryError“ erhalte, da je nach Projektgröße schnell der Arbeitsspeicher ausgehen kann.

Hier ist ein Beispiel für die Erhöhung der maximalen Heap-Größe von JVM. Außerdem ist es besser, das Verhältnis von -Xmx zu -Xms entweder 1:1 oder 1:1,5 beizubehalten, wenn Sie die Heap-Größe in Ihrer Java-Anwendung festlegen.

export JVM_ARGS="-Xms1024m -Xmx1024m"

Referenzlink

Standardmäßig verwendet JVM für die Entwicklung eine kleine Größe und eine kleine Konfiguration für andere leistungsbezogene Funktionen.Aber für die Produktion kann man z.B.(Darüber hinaus kann eine anwendungsserverspezifische Konfiguration vorhanden sein) -> (Wenn immer noch nicht genügend Speicher vorhanden ist, um die Anforderung zu erfüllen, und der Heap bereits die maximale Größe erreicht hat, tritt ein OutOfMemoryError auf.)

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size
-Xss<size>        set java thread stack size

-XX:ParallelGCThreads=8
-XX:+CMSClassUnloadingEnabled
-XX:InitiatingHeapOccupancyPercent=70
-XX:+UnlockDiagnosticVMOptions
-XX:+UseConcMarkSweepGC
-Xms512m
-Xmx8192m
-XX:MaxPermSize=256m (in java 8 optional)

Zum Beispiel:Auf der Linux-Plattform für den Produktionsmodus bevorzugte Einstellungen.

Nach dem Herunterladen und Konfigurieren des Servers auf diese Weise http://www.ehowstuff.com/how-to-install-and-setup-apache-tomcat-8-on-centos-7-1-rhel-7/

1. Erstellen Sie die Datei setenv.sh im Ordner /opt/tomcat/bin/

   touch /opt/tomcat/bin/setenv.sh

2.Öffnen und schreiben Sie diese Parameter, um den bevorzugten Modus festzulegen.

nano  /opt/tomcat/bin/setenv.sh 

export CATALINA_OPTS="$CATALINA_OPTS -XX:ParallelGCThreads=8"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+CMSClassUnloadingEnabled"
export CATALINA_OPTS="$CATALINA_OPTS -XX:InitiatingHeapOccupancyPercent=70"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UnlockDiagnosticVMOptions"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UseConcMarkSweepGC"
export CATALINA_OPTS="$CATALINA_OPTS -Xms512m"
export CATALINA_OPTS="$CATALINA_OPTS -Xmx8192m"
export CATALINA_OPTS="$CATALINA_OPTS -XX:MaxMetaspaceSize=256M"

3.service tomcat restart

Beachten Sie, dass die JVM mehr Speicher als nur den Heap verwendet.Zum Beispiel Java-Methoden, Thread-Stacks und native Handles werden im Arbeitsspeicher zugewiesen getrennt vom Heap, sowie JVM-interne Datenstrukturen.

Ich hatte das gleiche Problem mit der Java-Heap-Größe.

Ich habe zwei Lösungen, wenn Sie Java 5(1.5) verwenden.

  1. Installieren Sie einfach JDK1.6, gehen Sie zu den Einstellungen von Eclipse und legen Sie den JRE-Pfad von Jav1 1.6 fest, wie Sie ihn installiert haben.

  2. Überprüfen Sie Ihr VM-Argument und lassen Sie es so sein, wie es ist.Fügen Sie einfach eine Zeile unter allen Argumenten hinzu, die in VM-Argumenten als -Xms512m -Xmx512m -XX:MaxPermSize=... m(192m).

Ich denke, es wird funktionieren...

Ich habe irgendwo anders gelesen, dass Sie es versuchen können - java.lang.OutOfMemoryError abfangen und im Catch-Block können Sie alle Ressourcen freigeben, von denen Sie wissen, dass sie viel Speicher verbrauchen, Verbindungen schließen usw. und dann Folgendes tun: System.gc() Versuchen Sie dann noch einmal, was auch immer Sie tun wollten.

Ein anderer Weg ist allerdings dieser. Ich weiß nicht, ob das funktionieren würde, aber ich teste gerade, ob es in meiner Anwendung funktionieren wird.

Die Idee besteht darin, eine Garbage Collection durch den Aufruf von System.gc() durchzuführen, was bekanntermaßen den freien Speicher erhöht.Sie können dies weiterhin überprüfen, nachdem ein speicherfressender Code ausgeführt wurde.

//Mimimum acceptable free memory you think your app needs
long minRunningMemory = (1024*1024);

Runtime runtime = Runtime.getRuntime();

if(runtime.freeMemory()<minRunningMemory)
 System.gc();

Wenn Sie Ihre Speichernutzung zur Laufzeit überwachen müssen, können Sie Folgendes tun: java.lang.management Pauschalangebote MBeans Damit können Sie die Speicherpools in Ihrer VM (z. B. Eden Space, Tenured Generation usw.) und auch das Garbage-Collection-Verhalten überwachen.

Der von diesen MBeans gemeldete freie Heap-Speicherplatz variiert stark je nach GC-Verhalten, insbesondere wenn Ihre Anwendung viele Objekte generiert, die später GC-bearbeitet werden.Ein möglicher Ansatz besteht darin, den freien Heap-Speicherplatz nach jedem vollständigen GC zu überwachen, was Sie möglicherweise nutzen können, um eine Entscheidung über die Freigabe von Speicher durch persistente Objekte zu treffen.

Letztendlich ist es am besten, die Speichererhaltung so weit wie möglich zu begrenzen, während die Leistung akzeptabel bleibt.Wie bereits in einem früheren Kommentar erwähnt, ist der Speicher immer begrenzt, aber Ihre App sollte über eine Strategie für den Umgang mit Speichererschöpfung verfügen.

Beachten Sie, dass Sie, wenn Sie dies in einer Bereitstellungssituation benötigen, die Verwendung von Java WebStart (mit einer „Ondisk“-Version, nicht der Netzwerkversion – möglich in Java 6u10 und höher) in Betracht ziehen sollten, da es Ihnen ermöglicht, die verschiedenen Argumente für die JVM in einer Kreuzform anzugeben Plattformweg.

Andernfalls benötigen Sie einen betriebssystemspezifischen Launcher, der die benötigten Argumente festlegt.

Wenn dieses Problem in Wildfly 8 und JDK1.8 auftritt, müssen wir MaxMetaSpace-Einstellungen anstelle von PermGen-Einstellungen angeben.

Beispielsweise müssen wir die folgende Konfiguration in die Datei setenv.sh von Wildfly einfügen.JAVA_OPTS="$JAVA_OPTS -XX:MaxMetaspaceSize=256M"

Weitere Informationen finden Sie unter Problem mit dem Wildfly-Haufen

In Bezug auf Netbeans können Sie die maximale Heap-Größe festlegen, um das Problem zu lösen.

Gehen Sie zu „Ausführen“, dann -> „Projektkonfiguration festlegen“ -> „Anpassen“ -> „Ausführen“ des angezeigten Fensters -> „VM-Option“ -> geben Sie „-Xms2048m -Xmx2048m“ ein. .

Wenn Sie dem Objekt weiterhin Verweise zuweisen und beibehalten, füllen Sie den gesamten Speicher, der Ihnen zur Verfügung steht.

Eine Möglichkeit besteht darin, eine transparente Datei zu schließen und zu öffnen, wenn sie die Registerkarte wechseln (Sie behalten nur einen Zeiger auf die Datei, und wenn der Benutzer die Registerkarte wechselt, schließen und bereinigen Sie alle Objekte ...Dadurch wird die Dateiänderung langsamer ...aber...) und vielleicht nur 3 oder 4 Dateien im Speicher behalten.

Sie sollten außerdem Folgendes tun: Wenn der Benutzer eine Datei öffnet, laden Sie sie und fangen Sie alle OutOfMemoryError-Fehler ab. Schließen Sie dann (da es nicht möglich ist, die Datei zu öffnen) die Datei, bereinigen Sie ihre Objekte und warnen Sie den Benutzer, dass er ungenutzte Dateien schließen sollte Dateien.

Ihre Idee, den virtuellen Speicher dynamisch zu erweitern, löst das Problem nicht, da die Ressourcen der Maschine begrenzt sind. Sie sollten daher vorsichtig sein und mit Speicherproblemen umgehen (oder zumindest vorsichtig damit umgehen).

Ein paar Hinweise, die ich bei Speicherlecks gesehen habe, sind:

--> Denken Sie daran, dass Sie, wenn Sie etwas in eine Sammlung aufnehmen und es anschließend vergessen, immer noch einen starken Bezug dazu haben. Machen Sie also die Sammlung ungültig, bereinigen Sie sie oder machen Sie etwas damit ...Wenn nicht, ist es schwierig, ein Speicherleck zu finden.

-> Vielleicht kann die Verwendung von Sammlungen mit schwachen Referenzen (weakhashmap...) bei Speicherproblemen helfen, aber Sie muss Seien Sie vorsichtig damit, denn Sie könnten feststellen, dass das gesuchte Objekt eingesammelt wurde.

-> Eine weitere Idee, die ich gefunden habe, ist die Entwicklung einer persistenten Sammlung, die auf den am wenigsten genutzten Datenbankobjekten gespeichert und transparent geladen wird.Das wäre wahrscheinlich der beste Ansatz...

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top