Wie geht man mit "java.lang.OutOfMemoryError: Java heap space" Fehler?

Ich schreibe eine clientseitige Swing-Anwendung (grafischer Schriftdesigner) auf Java 5. Kürzlich bin ich in `java.lang.OutOfMemoryError: Java heap space"-Fehler, weil ich bei der Speichernutzung nicht konservativ bin. Der Benutzer kann eine unbegrenzte Anzahl von Dateien öffnen, und das Programm behält die geöffneten Objekte im Speicher. Nach einer kurzen Recherche fand ich Ergonomics in the 5.0 Java Virtual Machine und andere, die sagen, dass die JVM auf Windows-Rechnern standardmäßig eine maximale Heap-Größe von 64 MB vorgibt.

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

Ich könnte die max. Heap-Größe mit der Befehlszeilenoption von Java erhöhen, aber dazu müsste ich den verfügbaren Arbeitsspeicher ermitteln und ein Startprogramm oder Skript schreiben. Außerdem wird das Problem durch das Erhöhen auf eine unbegrenzte Maximalgröße nicht endgültig beseitigt.

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 wie automatischer virtueller Speicher, dynamisches Erweitern der Heap-Größe hinweisen könnten, wäre das großartig.

Lösung

Letztendlich haben Sie immer einen begrenzten maximalen Heap-Speicher zur Verfügung, egal auf welcher Plattform Sie arbeiten. Unter Windows 32 Bit sind das etwa 2 GB (nicht speziell der Heap, sondern der Gesamtspeicher pro Prozess). Es ist nur so, dass Java sich dafür entschieden hat, den Standardwert kleiner zu machen (vermutlich, damit der Programmierer keine Programme erstellen kann, die eine unkontrollierte Speicherzuweisung haben, ohne auf dieses Problem zu stoßen und genau prüfen zu müssen, was sie tun).

In Anbetracht dessen gibt es mehrere Möglichkeiten, entweder die benötigte Speichermenge zu ermitteln oder die verwendete Speichermenge zu reduzieren. Ein häufiger Fehler bei Garbage-Collecting-Sprachen wie Java oder C# besteht darin, Verweise auf Objekte aufrechtzuerhalten, die man nicht mehr verwendet, oder viele Objekte zuzuweisen, wenn man sie stattdessen wiederverwenden könnte. Solange Objekte einen Verweis auf sie haben, werden sie weiterhin Speicherplatz im Heap verwenden, da der Garbage Collector sie nicht löscht.

In diesem Fall können Sie einen Java-Speicher-Profiler verwenden, um festzustellen, welche Methoden in Ihrem Programm eine große Anzahl von Objekten zuweisen, und dann feststellen, ob es eine Möglichkeit gibt, dafür zu sorgen, dass sie nicht mehr referenziert werden, oder sie gar nicht erst zuzuweisen. Eine Möglichkeit, die ich in der Vergangenheit verwendet habe, ist "JMP" .

Wenn Sie feststellen, dass Sie diese Objekte aus einem bestimmten Grund allozieren und Referenzen beibehalten müssen (je nachdem, was Sie tun, könnte dies der Fall sein), müssen Sie nur die maximale Heap-Größe erhöhen, wenn Sie das Programm starten. Sobald Sie jedoch ein Speicherprofil erstellt haben und verstehen, 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 endlichen Menge an Speicher läuft (vielleicht abhängig von der Größe der Eingabe), werden Sie immer auf dieses Problem stoßen. Erst wenn Sie all diese Möglichkeiten ausgeschöpft haben, müssen Sie sich mit der Zwischenspeicherung von Objekten auf der Festplatte usw. befassen. An diesem Punkt sollten Sie einen sehr guten Grund haben, um zu sagen: "Ich brauche Xgb Speicher für etwas, und Sie können es nicht umgehen, indem Sie Ihre Algorithmen oder Speicherzuweisungsmuster verbessern. Im Allgemeinen ist dies nur bei Algorithmen der Fall, die mit großen Datenmengen arbeiten (z. B. eine Datenbank oder ein wissenschaftliches Analyseprogramm), und dann werden Techniken wie Caching und Memory Mapped IO nützlich.

Kommentare (1)

Führen Sie Java mit der Kommandozeilenoption -Xmx aus, die die maximale Größe des Heaps festlegt.

Siehe hier für Details.

Kommentare (3)

Ja, mit -Xmx können Sie mehr Speicher für Ihre JVM konfigurieren. Um sicher zu sein, dass Sie keinen Speicher vergeuden oder verlieren. Machen Sie einen Heap-Dump und verwenden Sie den Eclipse Memory Analyzer, um Ihren Speicherverbrauch zu analysieren.

Kommentare (1)