java.lang.OutOfMemoryError: Java-Heapspeicher

96

Beim Ausführen eines Multithreading-Programms wird der folgende Fehler angezeigt

java.lang.OutOfMemoryError: Java heap space

Der obige Fehler trat in einem der Threads auf.

  1. Meines Wissens wird der Heap-Speicher nur von Instanzvariablen belegt. Wenn dies korrekt ist, warum ist dieser Fehler aufgetreten, nachdem er einige Zeit ordnungsgemäß ausgeführt wurde, da zum Zeitpunkt der Objekterstellung Speicherplatz für beispielsweise Variablen zugewiesen wurde?

  2. Gibt es eine Möglichkeit, den Heap-Speicherplatz zu vergrößern?

  3. Welche Änderungen sollte ich an meinem Programm vornehmen, damit es weniger Heap-Speicherplatz beansprucht?

Yatendra Goel
quelle
4
Überprüfen Sie stackoverflow.com/questions/37335/…
JuanZe

Antworten:

104

Wenn Sie Ihren Heap-Speicherplatz vergrößern möchten, können Sie ihn java -Xms<initial heap size> -Xmx<maximum heap size>in der Befehlszeile verwenden. Standardmäßig basieren die Werte auf der JRE-Version und der Systemkonfiguration. Sie können erfahren Sie mehr über die VM - Optionen auf der Java - Website .

Ich würde jedoch empfehlen, Ihre Anwendung zu profilieren, um herauszufinden, warum Ihre Heap-Größe gegessen wird. NetBeans enthält einen sehr guten Profiler . Ich glaube, es verwendet die jvisualvmunter der Haube. Mit einem Profiler können Sie versuchen, herauszufinden, wo viele Objekte erstellt werden, wann Objekte Müll sammeln und vieles mehr.

Thomas Owens
quelle
1
Ich verwende Netbeans, weiß aber nicht, wie ich Profiler verwenden soll. Ich möchte mehr über den Profiler erfahren, damit ich damit Speicherlecks in meiner Anwendung finden kann.
Yatendra Goel
Ich habe einen Link zu einer Seite auf der NetBeans-Website ( profiler.netbeans.org ) hinzugefügt, die eine sehr gute Dokumentation des Profils enthält, von den Grundlagen bis zur fortgeschritteneren Verwendung.
Thomas Owens
Standardwerte ändern sich mit Java-Versionen. Es wäre schön, diese Informationen in Ihre Antwort aufzunehmen.
Dariusz
Habe gerade ein ähnliches Problem behoben und zuerst versucht: java -jar Division.jar -Xmx512m -Xms512m - dies gibt mir den gleichen Fehler, aber wenn ich es so mache: java -Xmx512m -Xms512m -jar Division.jar - alles ist in Ordnung. Daher ist auch die Reihenfolge der Parameter wichtig.
Hipokito
@hipokito Argumente, nachdem die JAR-Datei als args [] an die main () -Methode der JAR-Datei übergeben wurde
Asu
29

1.- Ja, aber es bezieht sich ziemlich genau auf den gesamten von Ihrem Programm verwendeten Speicher.

2.- Ja, siehe Java VM-Optionen

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size

Dh

java -Xmx2g Weisen Sie Ihrer App maximal 2 Gigabyte RAM zu

Aber Sie sollten zuerst sehen, ob Sie keinen Speicherverlust haben.

3.- Es kommt auf das Programm an. Versuchen Sie, Speicherlecks zu erkennen. Diese Frage wäre zu schwer zu beantworten. In letzter Zeit können Sie mit JConsole ein Profil erstellen, um herauszufinden, wohin Ihr Speicher gehen wird

OscarRyz
quelle
während welche (wahr);)
Gal Bracha
8

Auf dieser Website finden Sie weitere Informationen zum Speicher in der JVM: http://developer.streamezzo.com/content/learn/articles/optimization-heap-memory-usage

Ich habe es nützlich gefunden, mithilfe von visualgc zu beobachten, wie sich die verschiedenen Teile des Speichermodells füllen, um festzustellen, was geändert werden soll.

Es ist schwierig zu bestimmen, welcher Teil des Speichers gefüllt war, daher visualgc, da Sie möglicherweise nur den Teil ändern möchten, bei dem ein Problem vorliegt, anstatt nur zu sagen:

Fein! Ich werde der JVM 1G RAM geben.

Versuchen Sie genauer zu sagen, was Sie tun. Auf lange Sicht werden Sie wahrscheinlich das Programm besser dafür finden.

Um festzustellen, wo der Speicherverlust sein kann, können Sie Unit-Tests verwenden, indem Sie testen, was der Speicher vor und nach dem Test war, und wenn es eine zu große Änderung gibt, möchten Sie ihn möglicherweise untersuchen, müssen dies jedoch tun Führen Sie die Überprüfung durch, während Ihr Test noch ausgeführt wird.

James Black
quelle
6

Um die Größe des Heapspeichers zu erhöhen, können Sie beim Starten von Java das Argument -Xmx verwenden. z.B

-Xmx256M
Adamski
quelle
6

Sie können die Größe Ihres Heapspeichers unter dem folgenden Programm ermitteln.

public class GetHeapSize {
    public static void main(String[] args) {
        long heapsize = Runtime.getRuntime().totalMemory();
        System.out.println("heapsize is :: " + heapsize);
    }
} 

Dementsprechend können Sie die Größe des Heapspeichers auch mithilfe von Java -Xmx2g http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html erhöhen

user2663609
quelle
6
  1. Meines Wissens wird der Heap-Speicher nur von Instanzvariablen belegt. Wenn dies korrekt ist, warum ist dieser Fehler aufgetreten, nachdem er einige Zeit ordnungsgemäß ausgeführt wurde, da zum Zeitpunkt der Objekterstellung Speicherplatz für beispielsweise Variablen zugewiesen wurde?

Das bedeutet, dass Sie über einen bestimmten Zeitraum kontinuierlich mehr Objekte in Ihrer Anwendung erstellen. Neue Objekte werden im Heapspeicher gespeichert. Dies ist der Grund für das Wachstum des Heapspeichers.

Heap enthält nicht nur Instanzvariablen. Es werden alle nicht primitiven Datentypen (Objekte) gespeichert. Die Lebensdauer dieser Objekte kann kurz (Methodenblock) oder lang sein (bis auf das Objekt in Ihrer Anwendung verwiesen wird).

  1. Gibt es eine Möglichkeit, den Heap-Speicherplatz zu vergrößern?

Ja. Werfen Sie einen Blick auf dieses Orakel Artikel für weitere Details.

Es gibt zwei Parameter zum Festlegen der Heap-Größe:

-Xms : , legt die anfängliche und minimale Heap-Größe fest

-Xmx : , legt die maximale Heap-Größe fest

  1. Welche Änderungen sollte ich an meinem Programm vornehmen, damit es weniger Heap-Speicherplatz beansprucht?

Das hängt von Ihrer Bewerbung ab.

  1. Legen Sie den maximalen Heapspeicher gemäß Ihren Anwendungsanforderungen fest

  2. Verursachen Sie keine Speicherlecks in Ihrer Anwendung

  3. Wenn Sie in Ihrer Anwendung Speicherlecks finden, suchen Sie die Grundursache mithilfe von Profiling-Tools wie MAT , Visual VM , jconsole usw.. Beheben Sie die Lecks , sobald Sie die Grundursache gefunden haben.

Wichtige Hinweise von Oracle Artikel

Ursache: Die Detailmeldung Java-Heap-Speicherplatz zeigt an, dass das Objekt im Java-Heap nicht zugeordnet werden konnte. Dieser Fehler impliziert nicht unbedingt einen Speicherverlust.

Mögliche Gründe:

  1. Falsche Konfiguration (nicht genügend Speicher zuweisen)
  2. Die Anwendung enthält unbeabsichtigt Verweise auf Objekte, und dies verhindert, dass die Objekte durch Müll gesammelt werden
  3. Anwendungen, bei denen Finalizer übermäßig eingesetzt werden. Wenn eine Klasse über eine Finalisierungsmethode verfügt, wird der Speicherplatz von Objekten dieses Typs zum Zeitpunkt der Speicherbereinigung nicht zurückgefordert. Wenn der Finalizer-Thread mit der Finalisierungswarteschlange nicht Schritt halten kann, kann sich der Java-Heap füllen und diese Art von OutOfMemoryError-Ausnahme wird ausgelöst .

Verwenden Sie in einem anderen Fall bessere Garbage Collection-Algorithmen ( CMS oder G1GC ).

Schauen Sie sich diese Frage an, um G1GC zu verstehen

Ravindra Babu
quelle
5
  1. In den meisten Fällen ist der Code nicht optimiert. Geben Sie die Objekte frei, von denen Sie glauben, dass sie nicht weiter benötigt werden. Vermeiden Sie jedes Mal die Erstellung von Objekten in Ihrer Schleife. Versuchen Sie, Caches zu verwenden. Ich weiß nicht, wie es Ihrer Bewerbung geht. Bei der Programmierung gilt jedoch auch eine Regel des normalen Lebens

    Vorbeugung ist besser als Heilung. "Erstellen Sie keine unnötigen Objekte"

DKSRathore
quelle
3
  1. Lokale Variablen befinden sich auf dem Stapel. Der Heap-Platz wird von Objekten belegt.

  2. Sie können die -XmxOption verwenden.

  3. Grundsätzlich wird der Heap-Speicherplatz jedes Mal belegt, wenn Sie ein neues Objekt zuweisen, newund einige Zeit, nachdem auf das Objekt nicht mehr verwiesen wird, freigegeben. Stellen Sie daher sicher, dass Sie keine Verweise auf Objekte behalten, die Sie nicht mehr benötigen.

sepp2k
quelle
1

Nein, ich denke du denkst an Stapelplatz. Der Heap-Platz wird von Objekten belegt. Der Weg, um es zu erhöhen, ist -Xmx256m, wobei der 256 durch den Betrag ersetzt wird, den Sie in der Befehlszeile benötigen.

Yishai
quelle
1

Um diese Ausnahme zu vermeiden, fügen Sie bei Verwendung von JUnit und Spring Folgendes in jede Testklasse ein:

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
Aliuk
quelle
0

Gehen Sie in Netbeans zur Symbolleiste "Ausführen", -> "Projektkonfiguration festlegen" -> "Anpassen" -> "Ausführen" des angezeigten Windos -> "VM-Option" -> füllen Sie "-Xms2048m" aus -Xmx2048m '. Es könnte das Problem der Heap-Größe lösen.

Xiaogang
quelle