Java-GC:die ältere generation wird größer und größer und kann nicht zurückgefordert werden
Schreibe ich meine servlet-Programm und jconsole verwenden und jmap überwachen des Speicher-status.Ich finde, dass wenn mein Programm läuft , der Speicher-Pool "PS Alte Gen" wird immer größer und größer und schließlich mein servlet nicht reagieren auf jede Anfrage.
Dies ist der shotcut meiner JConsole Ausgabe:
Wenn ich auf "Ausführen GC" - Taste, passiert Nichts.
So , um die details zu sehen ,benutze ich jmap-dump details:
Und das ist mein JConsole VM Inhaltsangabe Ausgabe:
Jemand kann mir helfen raus zu bekommen was das problem sein kann?Ihr wissen , das GC "PS MarkSweep" und "PS Ausplündern" ist die Standard-GC für meine Server-JVM.
Danke.
Finde ich ein sehr komisches Phänomen:Während 15 Stunden von 18:00 Uhr gestern 09::00 von heute ,so scheint es, dass GC auf "PS Old-Gen" noch nie aufgetreten , das machen die verwendeten Speicher von der alten generation wird immer größer und größer.ich habe gerade manuell klicken Sie auf "Ausführen GC" - Schaltfläche ,es scheint, dass dieses GC ist sehr effektiv und beanspruchen viel Speicherplatz. Aber warum die Alte generation GC nicht automatisch geschehen, für eine so lange Zeit? Wir können sehen, dass vor 18:00 von gestern , die alte generation GC richtig funktioniert.
- Es scheint ziemlich klar, dass Sie eine große
LinkedHashMap
mit über 4 Millionen strings. Wenn ich du wäre, würde ich konzentrieren sich auf, herauszufinden, was die Karte ist, ob es gebraucht wird und, wenn es nicht ist, warum es beibehalten wird. (P. S. Es könnte sein, dass es mehrereLinkedHashMaps
hinzufügen, dass bis auf die oben genannten. Dies ändert sich nicht an meine Ratschläge.) - Und vielen Dank für einen klar formulierten Frage. (+1)
- Ein servlet wird nur einmal instanziert, so hat er erklärt-Attribut, alle threads werden in der Lage sein, es zu benutzen. Also, wenn Ihr servlet-Implementierung enthält eine große Sammlung, vielleicht sollten Sie prüfen, wie es wächst und wenn es zurückgesetzt werden kann.
- Aber in meinem servlet, die ich nicht definieren statische Variablen oder Instanzvariablen.Alle meine Daten-intensiven Variablen sind definiert in der Methode.Bei der Methode zurückgegeben werden , diese Variablen sollten zurückgefordert werden,richtig?
- Vielleicht eher, als eine große HashMap ist eine HashMap, die Punkte in eine HashMap, die Punkte in eine HashMap ... Oder etwas in der Natur.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Vorausgesetzt, dass Sie nicht das hinzufügen der option " - histo:live, wenn Sie mit der Einnahme wurden die jmap, die in einen Bericht mit Müll + live-Objekte, und unter Hinweis auf die Speicher-drop passiert, wenn du manuell auf "Ausführen GC" - Taste, ich bezweifle, dass die Anwendung nicht über einen memory-leak, aber ein schlechtes Objekt-promotion-rate von der Jungen Generation zur Alten Gen. Schließlich die Alte Gen gefüllt werden und wird eine vollständige GC aus der Anwendung zu gehen nicht reagiert.
Wenn meine Annahme richtig ist, ich denke, deine Strategie sollte sein, zu minimieren, die Förderung der Objekte zur alten gen. Anstatt sich Gedanken über das, was zu tun ist, um klar aus der Alten Gen, die deutlich teurer ist. Bezogen auf die unten Kommentare, die Sie erwähnt haben, ich denke, Ihr Antrag hat einen kleinen Speicher-Footprint (< 0,5 G ), bezogen auf die max zugewiesenen Speicher 7G .
So gibt es einige Dinge, die Sie tun können.
Stimmen Sie die Anwendung zur Minimierung der Antwortzeiten von Transaktionen, so dass die Objekte wird der Müll gesammelt, bevor Sie wurden gefördert, um die Alte Gen
Erhöhen der Junge Gen Größe. Sie haben seit rund 7 GB zu spielen, warum nicht, die Sie zuordnen, etwa 2 - 3 GB Junge Generation für einen start ( ich.e -XX:NewSize=2g ). Eine Neue, größere Größe zu reduzieren, die Häufigkeit der PCSacavenge ( Junge Sammlungen) und senkt die rate der Alterung der live-Objekte.
Dann starten einstellen -XX:MaxTenuringThreshold=n . Können Sie uns die gc.log -XX:+PrintTenuringDistribution. Größe der survivor-Verhältnisse -XX:SurvivorRatio=n. Beachten Sie, dass standardmäßig -XX:+UseAdaptiveSizePolicy und dieser wird verändern die ursprüngliche Größe der Survivor-Verhältnisse dynamisch. Oder sonst können Sie überspringen die Bestimmung der Größe der Survivor-Verhältnisse verlassen der AdaptiveSizePolicy um die Arbeit zu tun. Aber ich bin kein großer fan von AdaptiveSizePolicy.
Zusammen mit AdaptiveSizePolicy können Sie -XX:MaxGCPauseMillis=n, um zu geben, ein Indiz dafür, dass der Garbage Collector in Bezug auf die Pausen, die Sie erwarten in Ihrer Anwendung bei der Klärung der Alte Gen. auf diese Weise den Sammler wird versuchen zu erreichen, die MaxGCPauseMillis Sie nicht warten, bis es zu viel Arbeit zu tun.
Sonst können Sie umstellen auf CMS collector ist gebaut, um zu behandeln, response-Zeit, Fragen wie diese.
Naja, ich denke, wenn die ersten beiden Schritte das problem behebt, dann lassen Sie den rest beiseite. Sie müssen nicht verderben einer gut Laufenden app durch das hinzufügen einige zusätzliche Sachen. Wichtig ist, haben Sie die Optimierung der GC-Schritt für Schritt.
Ihre Speicherverlust happes in MongoDB-code. Die große Anzahl von map-Einträge, die Sie sehen, sind wahrscheinlich die Interna von
BasicDBObject
(Platz #6 in Ihrem dump), die sichHashMap
. Sie können in der Lage sein, das Problem zu beheben durch die Neukonfiguration der MongoDB-Komponente.