Java-Speicherfehler

7

Warum ist dieser folgende Code

? %Vor%

erzeugt einen nicht ausreichenden Speicherfehler

Aber dieser Code nicht

%Vor%

Ich kann sehen, dass es etwas damit zu tun hat, dass die Liste entweder innerhalb der while-Schleife oder außerhalb davon erstellt wird, aber ich bin unsicher, warum warum das passiert.

    
Donald 14.06.2017, 05:58
quelle

8 Antworten

10

Im ersten Fall haben Sie eine einzige ArrayList -Instanz, und Sie fügen neue Object -Instanzen hinzu, bis der Speicher voll ist.

Im zweiten Fall erstellen Sie eine neue ArrayList in jeder Iteration der while -Schleife und fügen 1000000 Object Instanzen hinzu, was bedeutet, dass die in der vorherigen Iteration erstellte ArrayList und die 1000000 Object Instanzen, die es enthält, können Garbage Collected sein, da das Programm keine Referenzen mehr auf sie hat.

Beachten Sie, dass das zweite Snippet auch zu einem Speichermangel führen kann, wenn die neuen Object s schneller erstellt werden als der Garbage Collector die alten freigeben kann, dies hängt jedoch von der JVM-Implementierung ab.

    
Eran 14.06.2017, 05:59
quelle
5

Im ersten Snippet wird die Liste außerhalb der Schleife erstellt (und beibehalten!), Sie fügen also endlos Elemente hinzu, bis Sie den gesamten verfügbaren Speicher belegt haben.

Im zweiten Snippet erstellt jede Iteration der while -Schleife ein neues ArrayList -Objekt. Da Sie nach dem Ende der Iteration keine Referenz mehr auf diese Instanz haben, ist diese Liste für die Garbage Collection geeignet, sodass die alten Listen immer wieder freigegeben werden und Sie Ihren Speicher nicht erschöpfen.

    
Mureinik 14.06.2017 06:01
quelle
4

In Ihrem zweiten Fall ist die Liste, die erstellt wurde (und wo die Elemente hinzugefügt werden), nicht mehr gültig und kann für GC verwendet werden. Dies wird benötigt, um Speicher für die neue ArrayList zu erstellen. Somit wird für jede Iteration ein neuer ArrayList erstellt und dann wird er für GC (wenn die Schleife endet) geeignet. Daher werden diese Objekte, wenn der Speicher niedrig ist, GCed.

Im ersten Fall fügen Sie Elemente zum selben ArrayList hinzu. Nichts wird gewertet.

    
TheLostMind 14.06.2017 06:01
quelle
3

Wenn Sie die Liste innerhalb der while-Schleife erstellen, wird Ihre vorherige Liste gelöscht, und Sie haben eine neue leere Liste. Danach wird Ihr Speicher vom Java Garbage Collector freigegeben und Sie fügen 1000000 Elemente zur Liste hinzu. Dann wird eine neue Liste erstellt und alles wiederholt sich.

    
Wernerson 14.06.2017 06:02
quelle
3

Im ersten Szenario wird das list-Objekt außerhalb der while-Schleife deklariert, die wiederum unbegrenzt läuft (while while (true)), also fügt es so lange hinzu, bis es keinen Speicher mehr hat, während es in der zweiten liegt habe die Liste innerhalb der while deklariert, die maximale Größe ist auf die Anzahl der Iterationen der for-Schleife beschränkt.

Jedes Mal, wenn die for-Schleife vorhanden ist, wird das Listenobjekt zurückgesetzt, das neu erstellt wurde, mit dem Sie beginnen, zu addieren. Sie haben also eine Obergrenze. Das alte Objekt wird als Müll gesammelt, wodurch die JVM gelöscht wird.

    
Saurabh Jhunjhunwala 14.06.2017 06:09
quelle
3

Diese Frage wird gut beantwortet von @Eran, @TheLostMind und allen, also setze ich nicht den gleichen Punkt, ich möchte nur die Gelegenheit nutzen, einen Punkt darauf zu legen, wie SoftReference und WeakReference hilft, die Ausnahme wegen zu wenig Speicher zu verzögern.

Führen Sie den Code mit den JVM-Argumenten als -Xms64m -Xmx64m aus, damit Sie die Ergebnisse schnell sehen können.

%Vor%     
hagrawal 14.06.2017 09:26
quelle
2

Im ersten Beispiel erstellen Sie eine Liste, fügen Elemente hinzu und beenden die Schleife. Im zweiten Beispiel erstellen Sie eine Liste, fügen ihr Objekte hinzu, erstellen dann eine neue -Liste, fügen eine Reihe von Dingen hinzu und wiederholen unendlich . Da Ihre Variable im ersten Beispiel außerhalb der Schleife erstellt wird, gibt es nur eine Liste zu füllen.

    
CodingNinja 14.06.2017 06:07
quelle
2

Der einzige Unterschied zwischen den beiden Codes ist die Position der Liste List = new ArrayList & lt; & gt; (); Linie. Für den ersten Code deklariert ArrayList außerhalb der while-Schleife und fügt der ArrayList-Instanz unendlich viele Objekte hinzu, so dass nicht genügend Speicher vorhanden ist. Andererseits deklariert der zweite ArrayList innerhalb der while-Schleife, so dass er nach jedem Schleifenzyklus (viele ArrayList-Instanzen) eine neue ArrayListe instanziiert. Nach der Regel von Garbage Collector in Java werden die Instanzen des vorherigen Zyklus entfernt, da auf sie nicht mehr hingewiesen wird. Daher verhindert der GC in Java, dass im zweiten Fall nicht genügend Arbeitsspeicher zur Verfügung steht.

    
GentleCoder 19.06.2017 05:04
quelle

Tags und Links