Speicherverlust bedeutet, dass das Programm, nachdem es Speicher beantragt hat, den zugewiesenen Speicherplatz nicht freigeben kann. Speicherüberlauf bedeutet, dass, wenn das Programm Speicher beantragt, nicht genügend Speicher für den Antragsteller vorhanden ist oder Speicherplatz zum Speichern von Int-Daten bereitgestellt wird, aber lange Daten gespeichert werden, was dazu führt, dass der Speicher nicht ausreicht Es wird ein OOM-Fehler gemeldet. Die Anhäufung von Speicherlecks führt schließlich zu einem Speicherüberlauf.
Die Betriebsumgebung dieses Tutorials: Windows7-System, Java8-Version, DELL G3-Computer.
bedeutet, dass das Programm den zugewiesenen Speicherplatz nicht freigeben kann, aber die Konsequenz angesammelter Speicherlecks ist Überlauf.
bedeutet, dass, wenn das Programm Speicher beantragt, nicht genügend Speicher für den Antragsteller vorhanden ist, oder mit anderen Worten, Ihnen wird Speicherplatz zum Speichern von Daten vom Typ int zur Verfügung gestellt Wenn Sie jedoch lange Datentypen speichern, reicht der Speicher nicht aus und es wird ein OOM-Fehler gemeldet, der sogenannte Speicherüberlauf.
Die Anhäufung von Speicherlecks führt schließlich zu einem Speicherüberlauf
Speicherüberlauf bedeutet, dass der von Ihnen gewünschte Speicherplatz den tatsächlich vom System zugewiesenen Speicherplatz übersteigt Zu diesem Zeitpunkt ist das System nicht in der Lage, Ihre Anforderungen zu erfüllen. Es wird ein Speicherüberlauffehler gemeldet.
Speicherverlust bedeutet, dass Sie beim System die Zuweisung von Speicher zur Verwendung (neu) beantragen, ihn aber nach der Verwendung nicht zurückgeben (löschen). Infolgedessen können Sie nicht mehr auf den Speicher zugreifen, den Sie beantragt haben (vielleicht Sie). put it (Die Adresse des Programms geht verloren) und das System kann sie nicht wieder dem gewünschten Programm zuordnen. Dies entspricht der Anmietung eines Schranks mit Schlüssel. Nachdem Sie Ihre Sachen verstaut und den Schrank verschlossen haben, verlieren Sie den Schlüssel oder geben ihn nicht zurück. Das Ergebnis ist, dass der Schrank von niemandem benutzt werden kann und nicht in den Müll gegeben werden kann recycelt, weil keine Informationen über ihn gefunden werden können.
Speicherüberlauf: Ein Teller kann nach dem Ausprobieren verschiedener Methoden nur 4 Früchte aufnehmen. Sie haben 5 hineingelegt, aber sie sind zu Boden gefallen und konnten nicht gegessen werden. Das ist Überlauf. Wenn beispielsweise ein Stapel verschoben wird, wenn der Stapel voll ist, kommt es zu einem Speicherplatzüberlauf, der als Überlauf bezeichnet wird. Wenn ein Stapel zurückgeschoben wird, wenn der Stapel leer ist, kommt es zu einem Speicherplatzüberlauf, der als Unterlauf bezeichnet wird. Das heißt, der zugewiesene Speicher reicht nicht aus, um die Folge von Datenelementen aufzunehmen, was als Speicherüberlauf bezeichnet wird. Um es ganz klar auszudrücken: Ich kann so viel nicht ertragen, deshalb werde ich einen Fehler melden.
Häufige Speicherlecks. Code mit Speicherverlusten wird mehrmals ausgeführt, was bei jeder Ausführung zu einem Speicherverlust führt.
Gelegentliche Speicherlecks. Code, der Speicherverluste verursacht, tritt nur unter bestimmten Umständen oder Vorgängen auf. Häufig und sporadisch sind relativ. Unter bestimmten Umständen kann das, was gelegentlich vorkommt, zur Normalität werden. Daher sind die Testumgebung und die Testmethoden für die Erkennung von Speicherlecks von entscheidender Bedeutung.
Einmaliger Speicherverlust. Der Code, der einen Speicherverlust verursacht, wird nur einmal ausgeführt, oder aufgrund von Algorithmusfehlern wird immer nur ein einziger Speicherblock verloren gehen. Wenn beispielsweise im Konstruktor einer Klasse Speicher zugewiesen wird, der Speicher jedoch im Destruktor nicht freigegeben wird, tritt der Speicherverlust nur einmal auf.
Impliziter Speicherverlust. Das Programm reserviert während der Ausführung kontinuierlich Speicher, gibt den Speicher jedoch erst am Ende frei. Streng genommen liegt hier kein Speicherverlust vor, da das Programm schließlich den gesamten angeforderten Speicher freigibt. Aber bei einem Serverprogramm, das tage-, wochen- oder sogar monatelang laufen muss, kann es auch dazu führen, dass der gesamte Systemspeicher erschöpft ist, wenn der Speicher nicht rechtzeitig freigegeben wird. Daher bezeichnen wir diese Art von Speicherverlust als impliziten Speicherverlust.
(1) Ursachen für einen Speicherüberlauf:
Die in den Speicher geladene Datenmenge ist zu groß, z. B. weil zu viele Daten entnommen werden
Es gibt Verweise auf Objekte in der Sammlungsklasse, die nach der Verwendung nicht gelöscht werden, sodass die JVM sie nicht recyceln kann.
Der Code enthält eine Endlosschleife oder die Schleife generiert zu viele doppelte Objekteinheiten;
Der zweite Schritt besteht darin, das Fehlerprotokoll zu überprüfen, um zu sehen, ob vor dem „OutOfMemory“-Fehler andere Ausnahmen oder Fehler vorliegen.
Konzentrieren Sie sich auf folgende Punkte:
Überprüfen Sie, ob in der Datenbankabfrage eine Abfrage vorhanden ist, um alle Daten auf einmal abzurufen. Wenn hunderttausend Datensätze gleichzeitig in den Speicher abgerufen werden, kann es im Allgemeinen zu einem Speicherüberlauf kommen. Dieses Problem ist relativ versteckt, da weniger Daten in der Datenbank vorhanden waren und es weniger wahrscheinlich zu Problemen kam. Nach dem Online-Gehen waren mehr Daten in der Datenbank vorhanden, und eine einzelne Abfrage konnte zu einem Speicherüberlauf führen. Versuchen Sie daher, Paging für Datenbankabfragen zu verwenden.
Überprüfen Sie, ob der Code Endlosschleifen oder rekursive Aufrufe enthält.
Überprüfen Sie, ob es eine große Schleife gibt, die immer wieder neue Objektentitäten generiert.
Überprüfen Sie, ob in der Datenbankabfrage eine Abfrage vorhanden ist, um alle Daten auf einmal abzurufen. Wenn hunderttausend Datensätze gleichzeitig in den Speicher abgerufen werden, kann es im Allgemeinen zu einem Speicherüberlauf kommen. Dieses Problem ist relativ versteckt, da weniger Daten in der Datenbank vorhanden waren und es weniger wahrscheinlich zu Problemen kam. Nach dem Online-Gehen waren mehr Daten in der Datenbank vorhanden, und eine einzelne Abfrage konnte zu einem Speicherüberlauf führen. Versuchen Sie daher, Paging für Datenbankabfragen zu verwenden.
Überprüfen Sie, ob Sammlungsobjekte wie List und MAP nach der Verwendung nicht gelöscht werden. Sammlungsobjekte wie List und MAP verfügen immer über Verweise auf die Objekte, sodass diese Objekte von GC nicht recycelt werden können.
Im vierten Schritt verwenden Sie das Speicheranzeigetool, um die Speichernutzung dynamisch anzuzeigen.
1.Java-Heap-Speicherüberlauf
Wenn die Ausnahme java.lang.OutOfMemoryError:Java-Heap-Speicherplatz auftritt, handelt es sich um einen Heap-Speicherüberlauf.
1), ProblembeschreibungDer JVM-Speichersatz ist zu klein, der für das Objekt erforderliche Speicher ist zu groß und diese Ausnahme wird ausgelöst, wenn beim Erstellen des Objekts Speicherplatz zugewiesen wird.
Verkehrs-/Datenspitzen, es gibt bestimmte Grenzen für die eigene Verarbeitung der Anwendung, wie zum Beispiel eine bestimmte Anzahl von Benutzern oder eine bestimmte Datenmenge. Wenn die Anzahl der Benutzer oder die Datenmenge plötzlich ansteigt und den erwarteten Schwellenwert überschreitet, werden die Vorgänge, die vor dem Spitzenwert normal ausgeführt wurden, gestoppt und Java lang.OutOfMemoryError: Java-Heap-Space-Fehler
2) ausgelöst. Beispielcode
2. Java-Heap-Speicherverlust
1), Problembeschreibung
Speicherverluste in Java sind Situationen, in denen einige Objekte von der Anwendung nicht mehr verwendet werden, aber von der Garbage Collection nicht erkannt werden. Daher sind diese nicht verwendeten Objekte weiterhin auf unbestimmte Zeit im Java-Heap-Speicher vorhanden. Die ständige Akkumulation löst schließlich java.lang.OutOfMemoryError aus.
2), Beispielcode
Wenn man den obigen Code ausführt, könnte man erwarten, dass er ewig ohne Probleme läuft, vorausgesetzt, dass die reine Caching-Lösung die zugrunde liegende Karte nur auf 10.000 Elemente erweitert, nicht alle Schlüssel sind bereits alle in der HashMap. Tatsächlich werden jedoch weiterhin Elemente hinzugefügt, da die Schlüsselklasse ihre Methode equal() nicht überschreibt. Da der durchgesickerte Code mit der Zeit ständig verwendet wird, verbrauchen die „zwischengespeicherten“ Ergebnisse letztendlich viel Java-Heap-Speicherplatz. Wenn verlorener Speicher den gesamten verfügbaren Speicher im Heap-Bereich füllt, kann die Speicherbereinigung ihn nicht bereinigen, java.lang.OutOfMemoryError.
3), LösungDie entsprechende Lösung ist relativ einfach: Schreiben Sie einfach die Equals-Methode neu:
3. Garbage Collection Timeout-Speicherüberlauf
1), Problembeschreibung: Wenn die Anwendung den gesamten verfügbaren Speicher erschöpft, wird das GC-Overhead-Limit überschritten Wenn der Fehler aufgetreten ist und der GC ihn mehrmals nicht löschen konnte, wird ein java.lang.OutOfMemoryError ausgelöst. Wenn die JVM viel Zeit mit der Ausführung von GC verbringt, ohne dass dies Auswirkungen hat, und sobald der gesamte GC-Prozess das Limit überschreitet, wird ein Fehler ausgelöst (die standardmäßige GC-Zeit der JVM-Konfiguration überschreitet 98 % und der recycelte Heap-Speicher beträgt weniger als 2). %).
2), Beispielcode
3), Lösung
Um den Objektlebenszyklus zu verkürzen, versuchen Sie, die Speicherbereinigung so schnell wie möglich durchzuführen.
4. Metaspace-Speicherüberlauf
1), Problembeschreibung
Überlauf des Metaspace, das System löst java.lang.OutOfMemoryError: Metaspace aus. Der Grund für dieses ungewöhnliche Problem liegt darin, dass das System über viel Code verfügt oder auf viele Pakete von Drittanbietern verweist oder dass dynamische Codegenerierung und Klassenladen verwendet werden, was zu einem großen Speicherbedarf im Metaspace führt.
2), Beispielcode
3), Lösung
Standardmäßig ist die Größe des Metaspace nur durch den lokalen Speicher begrenzt. Im Interesse der Leistung der gesamten Maschine sollte dieses Element jedoch so weit wie möglich eingestellt werden, um eine Unterbrechung des Betriebs der gesamten Maschine zu vermeiden.
Parameterkonfiguration optimieren, um Auswirkungen auf andere JVM-Prozesse zu vermeiden
-XX: MetaspaceSize, anfängliche Speicherplatzgröße, wird die Speicherbereinigung zum Entladen des Typs ausgelöst und der GC passt den Wert an: wenn freigegeben Wenn viel Speicherplatz vorhanden ist, verringern Sie den Wert entsprechend. Wenn nur wenig Speicherplatz freigegeben wird, erhöhen Sie den Wert entsprechend, wenn er MaxMetaspaceSize nicht überschreitet.
-XX:MaxMetaspaceSize, der maximale Speicherplatz, standardmäßig gibt es keine Begrenzung.
Zusätzlich zu den beiden oben genannten Optionen zur Größenangabe gibt es zwei GC-bezogene Attribute: -XX:MinMetaspaceFreeRatio. Nach GC wird der Prozentsatz der minimalen verbleibenden Metaspace-Speicherkapazität auf die durch den zugewiesenen Speicherplatz verursachte Speicherbereinigung reduziert. -XX: MaxMetaspaceFreeRatio, nach GC der Prozentsatz der maximalen verbleibenden Metaspace-Speicherkapazität, reduziert auf die durch die Freigabe von Speicherplatz verursachte Speicherbereinigung.
Vorsicht bei der Angabe von Drittanbieterpaketen
Wählen Sie Drittanbieterpakete sorgfältig aus und entfernen Sie unnötige Pakete. Dies wird nicht nur dazu beitragen, die Geschwindigkeit der Kompilierung und Verpackung zu verbessern, sondern auch die Geschwindigkeit der Remote-Bereitstellung zu verbessern.
Achten Sie auf Frameworks, die dynamisch generierte Klassen verwenden.
Bei Frameworks, die eine große Anzahl dynamisch generierter Klassen verwenden, sollten Stresstests durchgeführt werden, um zu überprüfen, ob die dynamisch generierten Klassen den Speicherbedarf überschreiten und eine Ausnahme ausgelöst wird .
5. Direkter Speicherüberlauf
1), Problembeschreibung
Es wird verwendet, wenn allocateDirect() in ByteBuffer verwendet wird. Viele JavaNIO-Frameworks (wie Netty) sind als andere Methoden gekapselt, ein java.lang. OutOfMemoryError: Wenn dieses Problem auftritt, wird eine Ausnahme für den direkten Pufferspeicher ausgelöst.
Ähnliche Probleme treten auf, wenn Sie direkt oder indirekt die allocateDirect-Methode in ByteBuffer verwenden, ohne sie zu löschen.
2), Beispielcode
3), Lösung
Wenn Sie häufig ähnliche Vorgänge haben, können Sie die Parameter -XX:MaxDirectMemorySize festlegen und den Speicher rechtzeitig löschen.
6. Stapelspeicherüberlauf
1), Problembeschreibung
Wenn ein Thread eine Java-Methode ausführt, erstellt die JVM einen neuen Stapelrahmen und schiebt ihn an die Spitze des Stapels. Zu diesem Zeitpunkt wird der neue Stapelrahmen zum aktuellen Stapelrahmen. Wenn die Methode ausgeführt wird, wird der Stapelrahmen zum Speichern von Parametern, lokalen Variablen, Zwischenanweisungen und anderen Daten verwendet.
Wenn sich eine Methode rekursiv aufruft, werden die von der neuen Methode generierten Daten (die auch als neuer Stapelrahmen verstanden werden können) an den Anfang des Stapels verschoben. Jedes Mal, wenn die Methode sich selbst aufruft, werden die Daten kopiert der aktuellen Methode und schieben Sie sie auf den Stapel. Daher erfordert jede Rekursionsebene die Erstellung eines neuen Stapelrahmens. Das Ergebnis ist, dass bei rekursiven Aufrufen immer mehr Speicher im Stapel verbraucht wird. Wenn sich rekursive Aufrufe millionenfach wiederholen, werden eine Million Stapelrahmen generiert. Dies führt zu einem Stapelspeicherüberlauf.
2), Beispielcode
3), Lösung
Wenn es tatsächlich rekursive Aufrufe im Programm gibt und ein Stapelüberlauf auftritt, können Sie die Größe -Xss erhöhen, um das Problem des Stapelspeicherüberlaufs zu lösen. Rekursive Aufrufe verhindern die Bildung einer Endlosschleife, da es sonst zu einem Stapelspeicherüberlauf kommt.
7. Speicherüberlauf beim Erstellen eines lokalen Threads
1), Problembeschreibung
Der Thread belegt im Grunde nur den Speicherbereich außer dem Heap Heap: Dem Thread kann kein Speicherbereich zugewiesen werden. Dies liegt entweder daran, dass der Speicher selbst nicht ausreicht, oder der Heap-Speicherplatz ist zu groß, was dazu führt, dass nicht mehr viel Speicher übrig bleibt, und weil der Thread selbst Speicher belegt ist nicht genug.
2), Beispielcode
3), Lösung
Überprüfen Sie zunächst, ob die Anzahl der Threads mit der Shell begrenzt ist. Wenn dies das Problem ist, müssen Sie dies tun Passen Sie die maximal unterstützte Anzahl des Systems an.
Versuchen Sie bei der täglichen Entwicklung sicherzustellen, dass die maximale Anzahl von Threads kontrollierbar ist, und verwenden Sie den Thread-Pool nicht willkürlich. Es kann nicht unbegrenzt wachsen.
8. Speicherüberlauf über den Swap-Bereich hinaus
1), Problembeschreibung
Während des Startvorgangs von Java-Anwendungen können Sie den angegebenen erforderlichen Speicher durch -Xmx und andere ähnliche Startparameter begrenzen. Wenn der von der JVM angeforderte Gesamtspeicher größer ist als der verfügbare physische Speicher, beginnt das Betriebssystem mit der Konvertierung des Inhalts vom Speicher auf die Festplatte.
Im Allgemeinen gibt die JVM den Fehler „Nicht genügend Swap-Speicherplatz“ aus. Dies bedeutet, dass die Fehlermeldung die Größe des nativen Heaps enthält, wenn die Anwendung den nativen JVM-Heap nicht zum Zuweisen von Speicher anfordert und der native Heap bald erschöpft ist Zuordnungsfehler (in Bytes) und der Grund, warum die Anfrage fehlgeschlagen ist.
2) Lösung
Erhöhen Sie die Größe des System-Swap-Bereichs, wenn der Swap-Bereich verwendet wird. Diese Methode wird in der Produktionsumgebung nicht empfohlen Speicher, der den physischen Speicher des Systems überschreitet. Zweitens entfernen Sie den System-Swap-Bereich und verwenden Sie den Systemspeicher nur, um die Anwendungsleistung sicherzustellen.
9. Array-Überlauf: Speicherüberlauf: Manchmal wird die angeforderte Array-Größe überschritten ist eine Grenze für die maximale Größe, die je nach Plattform variiert, normalerweise aber zwischen 1 und 2,1 Milliarden Elementen liegt. Wenn der Fehler „Angeforderte Array-Größe überschreitet VM-Grenze“ auftritt, bedeutet dies, dass die Anwendung versucht, ein Array zuzuweisen, das größer ist, als die Java Virtual Machine unterstützen kann. Bevor die JVM einem Array Speicher zuweist, führt sie eine plattformspezifische Prüfung durch: ob die zugewiesene Datenstruktur auf dieser Plattform adressierbar ist. 2), Beispielcode
Das Folgende ist der Code. Das Array überschreitet die maximale Grenze.
3), Lösung
Daher muss die Array-Länge innerhalb des von der Plattform zugelassenen Längenbereichs liegen. Allerdings ist dieser Fehler im Allgemeinen selten, hauptsächlich weil der Index eines Java-Arrays vom Typ int ist. Die größte positive ganze Zahl in Java ist 2^31 - 1 = 2.147.483.647. Und plattformspezifische Grenzwerte können dieser Zahl sehr nahe kommen, zum Beispiel: In meiner Umgebung (64-Bit-MacOS, mit Jdk1.8) kann ich Arrays mit Längen von bis zu 2.147.483.645 (Integer.MAX_VALUE-2) initialisieren. Wenn die Länge des Arrays um 1 erhöht wird, um nteger.MAX_VALUE-1 zu erreichen, tritt ein OutOfMemoryError auf.
10. System tötet Prozessspeicherüberlauf ab
1) Problemübersicht Bevor wir dieses Problem beschreiben, machen wir uns mit einigen Betriebssystemkenntnissen vertraut: Das Betriebssystem basiert auf dem Konzept von Prozessen, und diese Prozesse sind in der Kernel Im Betrieb gibt es einen ganz besonderen Prozess namens „Out of Memory Killer“. Wenn der Kernel feststellt, dass das System nicht über genügend Speicher verfügt, wird der OOM-Killer aktiviert, prüft, welcher Prozess derzeit den meisten Speicher belegt, und beendet dann den Prozess. Im Allgemeinen wird der Fehler „Nicht genügend Arbeitsspeicher: Prozess beenden oder untergeordnetes Element opfern“ ausgelöst, wenn der verfügbare virtuelle virtuelle Speicher (einschließlich Auslagerungsspeicher) so weit verbraucht ist, dass das gesamte Betriebssystem gefährdet ist. In diesem Fall wählt OOM Killer den „Rogue-Prozess“ aus und beendet ihn.
2) Beispielcode Wenn genügend Speicher vorhanden ist, tritt dieses Problem nicht auf. Zusammenfassend lässt sich sagen, dass durch die oben genannten 10 Arten von Speicherüberlaufsituationen jeder weiß, wie er das Problem lösen kann, wenn er tatsächlich darauf stößt. Beim tatsächlichen Codieren sollten Sie auch Folgendes beachten: JAR-Pakete von Drittanbietern sollten eingeführt werden Sorgfältig und entschlossen entfernt. Nutzlose JAR-Pakete, um die Kompilierungsgeschwindigkeit und die Systemspeichernutzung zu verbessern.Bei großen Objekten oder Anwendungen mit großem Speicher muss eine Optimierung durchgeführt werden, um die Verarbeitungsleistung zu verbessern und den Objektlebenszyklus zu verkürzen.
Versuchen Sie, die Anzahl der Threads festzulegen, um sicherzustellen, dass der von Threads belegte Speicher kontrollierbar ist. Wenn eine große Anzahl von Threads benötigt wird, muss die maximale Anzahl offener Verbindungen des Betriebssystems optimiert werden.Bei rekursiven Aufrufen muss auch der Grad der Rekursion kontrolliert werden, er darf nicht zu hoch sein und die Tiefe des Stapels überschreiten.
Je größer der dem Stapel zugewiesene Speicher ist, desto besser, denn je größer der Stapelspeicher und je mehr Threads, desto mehr Platz bleibt nicht mehr für den Heap übrig und es ist einfach, OOM auszulösen. Im Allgemeinen gibt es kein Problem mit den Standardparametern der JVM (einschließlich Rekursion).
Empfohlene verwandte Video-Tutorials: Java-Video-Tutorial
Das obige ist der detaillierte Inhalt vonWas sind Speicherlecks und Speicherüberläufe in Java?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!