Vorwort Bei einem seit 4 Jahren laufenden Java EE-Webprojekt kam es in letzter Zeit häufig zu der Rückmeldung von Kunden, dass sich das System nicht öffnen lässt. Ich habe mich beim Server angemeldet, um den Dienst zu überprüfen, und festgestellt, dass Tomcat automatisch heruntergefahren wurde. Es passiert grundsätzlich alle 3 bis 4 Tage. Das Betriebs- und Wartungspersonal dachte zunächst, dass andere Dienste den Tomcat-Dienst beendet hätten, und nahm dies nicht ernst. Die Lösung bestand darin, Tomcat direkt neu zu starten. Schließlich geriet die Situation außer Kontrolle und die Kunden beschwerten sich über das Betriebs- und Wartungspersonal, woraufhin ihm ein Monatslohn für seine Leistung abgezogen wurde. Die Lösung für diesen Fehler kam mir nach vielem Hin und Her. Nachdem Sie die Aufgabe erhalten haben, können Sie sich einfach an die Arbeit machen. Es gibt keinen Fehler, der nicht behoben werden kann. Die Betriebsumgebung des Systems ist wie folgt:
Überprüfen Sie die Protokolle. Wenn Tomcat abstürzt, wird im Bin-Verzeichnis von Tomcat eine Protokolldatei mit der Bezeichnung „hs_err“ generiert. Öffnen Sie die neueste Protokolldatei. Als Erstes sehen Sie den folgenden Absatz: # Es ist nicht genügend Speicher vorhanden, um die Java Runtime Environment fortzusetzen. # Die native Speicherzuweisung (malloc) konnte 32756 Bytes für ChunkPool::allocate nicht zuweisen. # Mögliche Gründe: # Das System verfügt nicht über genügend physischen RAM oder Swap-Speicher # Im 32-Bit-Modus wurde die Prozessgrößenbeschränkung erreicht # Mögliche Lösungen: # Reduzieren Sie die Speicherlast des Systems # Erhöhen Sie den physischen Speicher oder den Swap-Speicher # Überprüfen Sie, ob der Swap-Backing-Store voll ist # Verwenden Sie 64-Bit-Java auf einem 64-Bit-Betriebssystem # Java-Heapgröße verringern (-Xmx/-Xms) # Anzahl der Java-Threads verringern # Java-Thread-Stack-Größen verringern (-Xss) # Größeren Code-Cache mit -XX:ReservedCodeCacheSize= einstellen # Diese Ausgabedatei ist möglicherweise abgeschnitten oder unvollständig. # # Nicht genügend Arbeitsspeicherfehler (allocation.cpp:211), pid=7864, tid=6556 # # JRE-Version: Java(TM) SE Runtime Environment (7.0_79-b15) (Build 1.7.0_79-b15) # Java VM: Java HotSpot(TM) Server VM (24.79-b02, gemischter Modus, Windows-x86) # Schreiben des Core Dumps fehlgeschlagen. Dies bedeutet wahrscheinlich, dass nicht genügend Speicher vorhanden ist, um 32756 Byte Speicherplatz zuzuweisen. Hier sind einige Lösungen: 1. Reduzieren Sie die Systemspeicherlast. 2. Erhöhen Sie den physischen Speicher oder den Swap-Speicher. 3. Verwenden Sie 64-Bit-JDK auf einem 64-Bit-Betriebssystem; 4. Reduzieren Sie die Java-Heap-Größe; 5. Reduzieren Sie die Anzahl der Java-Threads. 6. Reduzieren Sie die Größe des Java-Thread-Stacks. Aus dem obigen Inhalt können wir schließen, dass die JVM nicht 32756 Byte Speicherplatz zuweisen kann. Von dem Moment an, als ich die Aufgabe erhielt, dachte ich immer, dass es sich um einen JVM-Konfigurationsfehler handelte, der zu unzureichendem Speicher führte, und ich nur die Konfiguration der neuen und alten Generation anpassen musste. Sehen Sie sich weiterhin die Protokolldatei an und suchen Sie die Zeile „GC Heap History (10 events):“, die die Änderungen im Heap während der letzten 10 Garbage Collections der JVM aufzeichnet. GC Heap-Verlauf (10 Ereignisse): Ereignis: 572312.299 GC-Heap vorher {Heap vor GC-Aufrufen=5046 (vollständig 357): PSYoungGen gesamt 201472K, genutzt 200685K [0x573c0000, 0x63bc0000, 0x63bc0000) Eden Space 198144K, 100 % genutzt [0x573c0000,0x63540000,0x63540000) vom Speicherplatz 3328K, 76% genutzt [0x63540000,0x637bb528,0x63880000) auf Speicherplatz 3328K, 0% genutzt [0x63880000,0x63880000,0x63bc0000) ParOldGen gesamt 843776K, genutzt 422602K [0x23bc0000, 0x573c0000, 0x573c0000) Objektspeicherplatz 843776K, 50% genutzt [0x23bc0000,0x3d872b18,0x573c0000) PSPermGen gesamt 262144K, genutzt 51848K [0x03bc0000, 0x13bc0000, 0x23bc0000) Objektspeicherplatz 262144K, 19% genutzt [0x03bc0000,0x06e62138,0x13bc0000) Ereignis: 572312.305 GC-Heap nach Heap nach GC-Aufrufen = 5046 (vollständig 357): PSYoungGen gesamt 201472K, genutzt 1103K [0x573c0000, 0x63bc0000, 0x63bc0000) Eden Space 198144K, 0 % genutzt [0x573c0000,0x573c0000,0x63540000) vom Speicherplatz 3328K, 33% verwendet [0x63880000,0x63993c90,0x63bc0000) auf Speicherplatz 3328K, 0% genutzt [0x63540000,0x63540000,0x63880000) ParOldGen gesamt 843776K, genutzt 423618K [0x23bc0000, 0x573c0000, 0x573c0000) Objektspeicherplatz 843776K, 50% genutzt [0x23bc0000,0x3d970b18,0x573c0000) PSPermGen gesamt 262144K, genutzt 51848K [0x03bc0000, 0x13bc0000, 0x23bc0000) Objektspeicherplatz 262144K, 19% genutzt [0x03bc0000,0x06e62138,0x13bc0000) } Ereignis: 572351.132 GC-Heap vorher {Heap vor GC-Aufrufen=5047 (vollständig 357): PSYoungGen gesamt 201472K, genutzt 199247K [0x573c0000, 0x63bc0000, 0x63bc0000) Eden Space 198144K, 100 % genutzt [0x573c0000,0x63540000,0x63540000) vom Speicherplatz 3328K, 33% verwendet [0x63880000,0x63993c90,0x63bc0000) auf Speicherplatz 3328K, 0% genutzt [0x63540000,0x63540000,0x63880000) ParOldGen gesamt 843776K, genutzt 423618K [0x23bc0000, 0x573c0000, 0x573c0000) Objektspeicherplatz 843776K, 50% genutzt [0x23bc0000,0x3d970b18,0x573c0000) PSPermGen gesamt 262144K, genutzt 51848K [0x03bc0000, 0x13bc0000, 0x23bc0000) Objektspeicherplatz 262144K, 19% genutzt [0x03bc0000,0x06e62138,0x13bc0000) Ereignis: 572351.137 GC-Heap nach Heap nach GC-Aufrufen = 5047 (vollständig 357): PSYoungGen gesamt 201472K, genutzt 1615K [0x573c0000, 0x63bc0000, 0x63bc0000) Eden Space 198144K, 0 % genutzt [0x573c0000,0x573c0000,0x63540000) vom Speicherplatz 3328K, 48% verwendet [0x63540000,0x636d3ec8,0x63880000) auf Speicherplatz 3328K, 0% genutzt [0x63880000,0x63880000,0x63bc0000) ParOldGen gesamt 843776K, genutzt 423674K [0x23bc0000, 0x573c0000, 0x573c0000) Objektspeicherplatz 843776K, 50% genutzt [0x23bc0000,0x3d97eb18,0x573c0000) PSPermGen gesamt 262144K, genutzt 51848K [0x03bc0000, 0x13bc0000, 0x23bc0000) Objektspeicherplatz 262144K, 19% genutzt [0x03bc0000,0x06e62138,0x13bc0000) } Ereignis: 572398.649 GC-Heap vorher {Heap vor GC-Aufrufen=5048 (vollständig 357): PSYoungGen gesamt 201472K, genutzt 199759K [0x573c0000, 0x63bc0000, 0x63bc0000) Eden Space 198144K, 100 % genutzt [0x573c0000,0x63540000,0x63540000) vom Speicherplatz 3328K, 48% verwendet [0x63540000,0x636d3ec8,0x63880000) auf Speicherplatz 3328K, 0% genutzt [0x63880000,0x63880000,0x63bc0000) ParOldGen gesamt 843776K, genutzt 423674K [0x23bc0000, 0x573c0000, 0x573c0000) Objektspeicherplatz 843776K, 50% genutzt [0x23bc0000,0x3d97eb18,0x573c0000) PSPermGen gesamt 262144K, genutzt 51848K [0x03bc0000, 0x13bc0000, 0x23bc0000) Objektspeicherplatz 262144K, 19% genutzt [0x03bc0000,0x06e62138,0x13bc0000) Ereignis: 572398.655 GC-Heap nach Heap nach GC-Aufrufen = 5048 (vollständig 357): PSYoungGen gesamt 201472K, genutzt 1998K [0x573c0000, 0x63bc0000, 0x63bc0000) Eden Space 198144K, 0 % genutzt [0x573c0000,0x573c0000,0x63540000) vom Speicherplatz 3328K, 60% verwendet [0x63880000,0x63a73830,0x63bc0000) auf Speicherplatz 3328K, 0% genutzt [0x63540000,0x63540000,0x63880000) ParOldGen gesamt 843776K, genutzt 423703K [0x23bc0000, 0x573c0000, 0x573c0000) Objektspeicherplatz 843776K, 50% genutzt [0x23bc0000,0x3d985cc0,0x573c0000) PSPermGen gesamt 262144K, genutzt 51848K [0x03bc0000, 0x13bc0000, 0x23bc0000) Objektspeicherplatz 262144K, 19% genutzt [0x03bc0000,0x06e62138,0x13bc0000) } Ereignis: 576881.689 GC-Heap vorher {Heap vor GC-Aufrufen=5049 (vollständig 357): PSYoungGen gesamt 201472K, genutzt 200142K [0x573c0000, 0x63bc0000, 0x63bc0000) Eden Space 198144K, 100 % genutzt [0x573c0000,0x63540000,0x63540000) vom Speicherplatz 3328K, 60% verwendet [0x63880000,0x63a73830,0x63bc0000) auf Speicherplatz 3328K, 0% genutzt [0x63540000,0x63540000,0x63880000) ParOldGen gesamt 843776K, genutzt 423703K [0x23bc0000, 0x573c0000, 0x573c0000) Objektspeicherplatz 843776K, 50% genutzt [0x23bc0000,0x3d985cc0,0x573c0000) PSPermGen gesamt 262144K, genutzt 51850K [0x03bc0000, 0x13bc0000, 0x23bc0000) Objektspeicherplatz 262144K, 19% genutzt [0x03bc0000,0x06e62850,0x13bc0000) Ereignis: 576881.696 GC-Heap nach Heap nach GC-Aufrufen = 5049 (vollständig 357): PSYoungGen gesamt 201472K, genutzt 3155K [0x573c0000, 0x63bc0000, 0x63bc0000) Eden Space 198144K, 0 % genutzt [0x573c0000,0x573c0000,0x63540000) aus Speicherplatz 3328K, 94% verwendet [0x63540000,0x63854cb0,0x63880000) auf Speicherplatz 3328K, 0% genutzt [0x63880000,0x63880000,0x63bc0000) ParOldGen gesamt 843776K, genutzt 423703K [0x23bc0000, 0x573c0000, 0x573c0000) Objektspeicherplatz 843776K, 50% genutzt [0x23bc0000,0x3d985cc0,0x573c0000) PSPermGen gesamt 262144K, genutzt 51850K [0x03bc0000, 0x13bc0000, 0x23bc0000) Objektspeicherplatz 262144K, 19% genutzt [0x03bc0000,0x06e62850,0x13bc0000) } Ereignis: 580535.452 GC-Heap vorher {Heap vor GC-Aufrufen=5050 (vollständig 357): PSYoungGen gesamt 201472K, genutzt 201299K [0x573c0000, 0x63bc0000, 0x63bc0000) Eden Space 198144K, 100 % genutzt [0x573c0000,0x63540000,0x63540000) aus Speicherplatz 3328K, 94% verwendet [0x63540000,0x63854cb0,0x63880000) auf Speicherplatz 3328K, 0% genutzt [0x63880000,0x63880000,0x63bc0000) ParOldGen gesamt 843776K, genutzt 423703K [0x23bc0000, 0x573c0000, 0x573c0000) Objektspeicherplatz 843776K, 50% genutzt [0x23bc0000,0x3d985cc0,0x573c0000) PSPermGen gesamt 262144K, genutzt 51856K [0x03bc0000, 0x13bc0000, 0x23bc0000) Objektspeicherplatz 262144K, 19% genutzt [0x03bc0000,0x06e64228,0x13bc0000) Ereignis: 580535.459 GC-Heap nach Heap nach GC-Aufrufen = 5050 (vollständig 357): PSYoungGen gesamt 200960K, genutzt 1858K [0x573c0000, 0x63bc0000, 0x63bc0000) Eden Space 197632K, 0 % genutzt [0x573c0000,0x573c0000,0x634c0000) vom Speicherplatz 3328K, 55% verwendet [0x63880000,0x63a50be0,0x63bc0000) auf Speicherplatz 3584K, 0% genutzt [0x634c0000,0x634c0000,0x63840000) ParOldGen gesamt 843776K, genutzt 423703K [0x23bc0000, 0x573c0000, 0x573c0000) Objektspeicherplatz 843776K, 50% genutzt [0x23bc0000,0x3d985cc0,0x573c0000) PSPermGen gesamt 262144K, genutzt 51856K [0x03bc0000, 0x13bc0000, 0x23bc0000) Objektspeicherplatz 262144K, 19% genutzt [0x03bc0000,0x06e64228,0x13bc0000) } Nachdem ich den obigen Inhalt gelesen hatte, konnte ich nicht feststellen, dass der Tomcat-Flash-Absturz durch unzureichenden Speicherplatz in der alten, permanenten und neuen Generation verursacht wurde. Es gab mehrere vollständige GCs, die durch eine 100-prozentige Auslastung des Eden-Speicherplatzes verursacht wurden, nach der Speicherbereinigung kehrte der Speicherplatz im Eden-Bereich jedoch auf das normale Niveau zurück. Das Protokoll zeichnet auch die Heap-Nutzung auf, wenn Tomcat abstürzt: Haufen PSYoungGen gesamt 200960K, genutzt 95671K [0x573c0000, 0x63bc0000, 0x63bc0000) Eden Space 197632K, 47 % genutzt [0x573c0000,0x5cf5d230,0x634c0000) vom Speicherplatz 3328K, 55% verwendet [0x63880000,0x63a50be0,0x63bc0000) auf Speicherplatz 3584K, 0% genutzt [0x634c0000,0x634c0000,0x63840000) ParOldGen gesamt 843776K, genutzt 423703K [0x23bc0000, 0x573c0000, 0x573c0000) Objektspeicherplatz 843776K, 50% genutzt [0x23bc0000,0x3d985cc0,0x573c0000) PSPermGen gesamt 262144K, genutzt 51856K [0x03bc0000, 0x13bc0000, 0x23bc0000) Objektspeicherplatz 262144K, 19% genutzt [0x03bc0000,0x06e64228,0x13bc0000) Alles war so normal und doch gleichzeitig so seltsam. Ich habe die vorherigen Protokolle durchgesehen und der Inhalt war ähnlich. Ich habe die Protokolle ein paar Mal erneut gelesen und mich dieses Mal auf die in den Protokollen vorgeschlagenen Lösungen konzentriert: # Reduzieren Sie die Speicherlast des Systems # Erhöhen Sie den physischen Speicher oder den Swap-Speicher # Überprüfen Sie, ob der Swap-Backing-Store voll ist # Verwenden Sie 64-Bit-Java auf einem 64-Bit-Betriebssystem # Java-Heapgröße verringern (-Xmx/-Xms) # Anzahl der Java-Threads verringern # Java-Thread-Stack-Größen verringern (-Xss) Die folgenden Lösungen werden nicht übernommen:
Es bleiben nur folgende drei Lösungen übrig:
Um die Anzahl der Java-Threads zu reduzieren, müsste der Code geändert werden, was ebenfalls nicht praktikabel ist. Schließlich nur
Dies sind die beiden Lösungen. Fangen Sie hier an, dann wird es Licht geben. Schauen Sie sich zunächst die Lösung zur Reduzierung der Java-Thread-Stack-Größen (-Xss) an. Java-Threads benötigen zum Ausführen ebenfalls Speicherplatz. Der Parameter -Xss gibt die Größe jedes Thread-Stapels und die Speichergröße an, die jedem von der JVM gestarteten Thread zugewiesen wird. In JDK 1.4 sind es 256 K und in JDK 1.5 und höher 1 M. Die Parameter der Tomcat-JVM werden wie folgt eingestellt: JAVA_OPTS=%JAVA_OPTS% -server -Xms1024m -Xmx1024m -Xmn200M -XX:PermSize=256M -XX:MaxPermSize=512m -XX:SurvivorRatio=1 -Xss256k Die Stapelgröße jedes Java-Threads wurde über -Xss auf 256 KB eingestellt. Wenn Sie in der Java-Sprache einen Thread erstellen, erstellt die virtuelle Maschine ein Thread-Objekt im JVM-Speicher und erstellt gleichzeitig einen Betriebssystem-Thread. Der Speicher dieses System-Threads ist nicht JVMMemory, sondern der verbleibende Speicher im System (MaxProcessMemory - JVMMemory - ReservedOsMemory). Wenn ein Thread erstellt werden muss und der verbleibende Speicher des Betriebssystems nicht ausreicht, um ihn einem Java-Thread zuzuweisen, wird ein „Out of Memory“-Fehler gemeldet. Da die Java-Thread-Stack-Größe über -Xss auf 256 KB eingestellt wurde, wurde entschieden, diese Lösung nicht zu verwenden. Jetzt besteht die einzige verbleibende Lösung darin, die Java-Heap-Größe zu verringern (-Xmx/-Xms). Durch die Reduzierung der Heap-Größe bleibt genügend Speicherplatz für den Java-Thread-Stack übrig. Das 32-Bit-Windows-Betriebssystem weist jedem Prozess 2 GB Speicherplatz zu, abzüglich der maximalen Kapazität des Heaps und der maximalen Kapazität von PermSize. Die verbleibende Kapazität ist für den Java-Thread-Stapel reserviert. Nach der Analyse des Codes und vorheriger Fehlerprotokolle wurde festgestellt, dass der Fehler „Nicht genügend Arbeitsspeicher“ normalerweise bei etwa 350 Threads auftritt. Die geänderten JVM-Parameter sind wie folgt: JAVA_OPTS=%JAVA_OPTS% -server -Xms768m -Xmx768m -Xmn200M -XX:PermSize=256M -XX:MaxPermSize=512m -XX:SurvivorRatio=1 -Xss256k Bisher läuft das System seit einem Monat stabil und alle Parameteranzeigen liegen im normalen Bereich. Die maximale Heap-Auslastung beträgt lediglich 70 %. Zusammenfassen: 1. Nachdem ich den Fehler dieses Mal behoben hatte, vertiefte ich mein Verständnis der Java-virtuellen Maschine, insbesondere der Konzepte Thread-Stack, Speicherheap, persistente Generierung, neue Generation usw. 2. Lesen Sie die Protokolldateien sorgfältig durch und schließen Sie mögliche Lösungen Schritt für Schritt aus. Berücksichtigen Sie die Betriebsumgebung des Gesamtsystems und finden Sie eine sinnvolle Lösung. Das ist alles für diesen Artikel. Ich hoffe, dass der Inhalt dieses Artikels für Ihr Studium oder Ihre Arbeit von gewissem Referenzwert ist. Vielen Dank für Ihre Unterstützung von 123WORDPRESS.COM. Das könnte Sie auch interessieren:
|
<<: Detaillierte Erläuterung des Fehlerproblems der Case-When-Anweisung
Inhaltsverzeichnis Vorwort Grundlegende Konzepte ...
Inhaltsverzeichnis Vorwort Ziel Erster Schritt: S...
AWS – Amazons Cloud-Computing-Serviceplattform Ic...
In diesem Artikelbeispiel wird der spezifische Co...
Inhaltsverzeichnis 1. Weltweit registrierte Kompo...
In diesem Artikelbeispiel wird der spezifische Co...
Inhaltsverzeichnis Einführung in Docker Installat...
<br />Vor Kurzem hat UCDChina eine Artikelse...
Herunterladen und Installieren von JDK Schritt 1:...
1. Bereiten Sie die Umgebung vor (laden Sie nodej...
Inhaltsverzeichnis 1. Baidu Map API-Zugriff 2. Ve...
Inhaltsverzeichnis 1: Kapselungsidee 2. Verpackun...
Projektdokumentationsverzeichnis Div+CSS-Benennung...
Inhaltsverzeichnis Vorwort zx-Bibliothek $`Befehl...
Abfrage der Gesamtgröße aller Datenbanken So geht...