Frage

Kurzform: Das CMS Garbage Collector erscheint eine ständig wachsende Menge an Müll zu sammeln, andernfalls zu sein; schließlich füllt unsere JVM auf, und die Anwendung reagiert nicht mehr. Erzwingen eines GC über ein externes Tool (JConsole oder jmap -histo:live) reinigt es sofort auf.

UPDATE: Das Problem scheint die JTop Plugin für JConsole bezogen zu werden; wenn wir nicht JConsole laufen, oder es ohne die JTop Plugin laufen, das Verhalten geht weg.

(Technische Hinweise:.. Wir laufen Sun JDK 1.6.0_07, 32-bit, auf einem Linux 2.6.9 Box die JDK-Version Upgrade ist nicht wirklich eine Option, es sei denn, es gibt eine unvermeidliche, wichtiger Grund auch unsere System ist nicht mit einer Internet-Maschine, so Screenshots von JConsole angeschlossen, etc. ist keine Option.)

Wir sind derzeit unsere JVM mit den folgenden Flags ausgeführt wird:

-server -Xms3072m -Xmx3072m -XX:NewSize=512m -XX:MaxNewSize=512m 
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled 
-XX:CMSInitiatingOccupancyFraction=70 
-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps 
-XX:+DisableExplicitGC

Die Beobachtung des Speicher Graph in JConsole, gibt es eine vollständige GC, den alle ~ 15 Minuten oder so während der ersten Stunden unserer Anwendung der Lebensdauer läuft; nach jedem vollen GC, gibt es mehr und mehr Speicher noch in Gebrauch. Nach ein paar Stunden, schlägt das System einen stabilen Zustand, in dem es in der CMS alten gen 2 GB Speicher gebrauchte ungefähr ist.

Welche Geräusche wie ein klassisches Speicherleck, mit der Ausnahme, dass, wenn wir jedes Werkzeug verwenden, dass Kräfte eine vollständige GC (die „Collect Müll“ in JConsole schlagen oder jmap -histo:live läuft, usw.), die alte Generation fällt plötzlich auf ~ 500 MB verwendet und unsere Anwendung wird wieder ansprechbar für die nächsten Stunden (während dieser Zeit das gleiche Muster setzt sich fort -. nach jeder vollen GC, mehr und mehr von der alten Generation voll ist)

Eine Sache der Anmerkung: in JConsole berichtete die ConcurrentMarkSweep GC Zählung bei 0 bleiben, bis wir eine GC erzwingen mit jconsole / jmap / etc

.

Mit jmap -histo und jmap -histo:live in Folge, ich bin in der Lage zu bestimmen, dass die scheinbar nicht abgeholte Objekte bestehen aus:

  • mehr Millionen HashMaps und Anordnungen von HashMap$Entry (in einem Verhältnis 1: 1)
  • mehrere Millionen Vectors und Objektfelder (Verhältnis 1: 1, und etwa die gleiche wie die Anzahl der HashMaps)
  • mehr Millionen HashSet, Hashtable und com.sun.jmx.remote.util.OrderClassLoaders sowie Anordnungen von Hashtable$Entry (etwa der gleichen Anzahl von jedem, etwa halb so viele wie die HashMaps und Vektoren)

Es gibt einige Auszüge aus dem GC-Ausgang unten; meine Interpretation von ihnen scheint zu sein, dass das CMS GC ohne Failover auf den Stop-the-world GC abgebrochen zu werden. Bin ich falsch interpretiert diese Ausgabe irgendwie? Gibt es etwas, das das würde dazu führen?

Während der normalen Laufzeit werden die CMS GC Ausgangsblöcke aussehen etwa wie folgt aus:

36301.827: [GC [1 CMS-initial-mark: 1856321K(2621330K)] 1879456K(3093312K), 1.7634200 secs] [Times: user=0.17 sys=0.00, real=0.18 secs]
36303.638: [CMS-concurrent-mark-start]
36314.903: [CMS-concurrent-mark: 7.804/11.264 secs] [Times: user=2.13 sys=0.06, real=1.13 secs]
36314.903: [CMS-concurrent-preclean-start]
36314.963: [CMS-concurrent-preclean: 0.037/0.060 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
36314.963: [CMS-concurrent-abortable-preclean-start]
36315.195: [GC 36315.195: [ParNew: 428092K->40832K(471872K), 1.1705760 secs] 2284414K->1897153K(3093312K), 1.1710560 secs] [Times: user=0.13 sys=0.02, real=0.12 secs]
CMS: abort preclean due to time 36320.059: [CMS-concurrent-abortable-preclean: 0.844/5.095 secs] [Times: user=0.74 sys=0.05, real=0.51 secs]
36320.062: [GC[YG occupancy: 146166 K (471872 K)]36320.062: [Rescan (parallel), 1.54078550 secs]36321.603: [weak refs processing, 0.0042640 secs] [1 CMS-remark: 1856321K(2621440K)] 2002488K(3093312K), 1.5456150 secs] [Times: user=0.18 sys=0.03, real=0.15 secs]
36321.608: [CMS-concurrent-sweep-start]
36324.650: [CMS-concurrent-sweep: 2.686/3.042 secs] [Times: uesr=0.66 sys=0.02, real=0.30 secs]
36324.651: [CMS-concurrent-reset-start]
36324.700: [CMS-concurrent-reset: 0.050/0.050 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]

und dass es; die nächste Zeile wird die nächste ParNew GC sein.

Wenn wir einen GC jmap -histo erzwingen: leben, wir stattdessen bekommen:

48004.088: [CMS-concurrent-mark: 8.012/8.647 secs] [Times: user=1.15 sys=0.02, real=0.87 secs]
(concurrent mode interrupted)

, gefolgt von ~ 125 Zeilen der Form unter: (einige GeneratedMethodAccessor, einige GeneratedSerializationConstructorAccessor, einige GeneratedConstructorAccessor usw.)

[Unloading class sun.reflect.GeneratedMethodAccessor3]

, gefolgt von:

: 1911295K->562232K(2621440K), 15.6886180 secs] 2366440K->562232K(3093312K), [CMS Perm: 52729K->51864K(65536K)], 15.6892270 secs] [Times: user=1.55 sys=0.01, real=1.57 secs]

Vielen Dank im Voraus!

War es hilfreich?

Lösung

com.sun.jmx.remote.util.OrderClassLoader in der remote'ing Schicht für JMX und eine schnelle Überprüfung des Codes schlägt sie erstellt als Teil des unmarshalling Prozesses für Remoteanforderungen innerhalb der JVM verwendet. Die Lebensdauer dieser Classloader wird direkt an die Lebensdauer der Sache, die entordnet war so in Beziehung gesetzt werden, dass, sobald es nicht mehr alle Verweise auf das Ding könnte der Klassenlader freigegeben werden.

Ich wäre nicht überrascht, wenn in diesem Fall die Anwesenheit dieser Instanzen eine direkte Folge den Sie ist JConsole mit dem Treiben auf der JVM zu untersuchen. Und es sieht aus wie sie nur durch GC als Teil des normalen Betriebes gereinigt werden würden auf.

Ich denke, es ist möglich, es ist ein Fehler in der JMX-Implementierung (in einem relativ up-to-date JVM unwahrscheinlich scheint) oder haben Sie vielleicht einige benutzerdefinierte MBeans oder verwenden einige benutzerdefinierte JMX-Tools, die das Problem verursachen. Aber letztlich bin ich zu ahnen, die OrderClassLoader ist wahrscheinlich eine rot-Hering und die Ausgabe liegt an anderer Stelle (gestrichelte GC oder ein anderes Leck).

Andere Tipps

  

Technische Hinweise: wir laufen Sun JDK   1.6.0_07, 32-bit, auf einer Linux 2.6.9 Box. die JDK-Version Upgrade ist nicht   wirklich eine Option, es sei denn es gibt eine   unvermeidbar, Hauptgrund.

Mehrere neuere Java-Versionen haben Updates für das CMS Garbage Collector hatte. Bemerkenswerter 6u12, 6u14 und 6u18.

Ich bin kein Experte mit GC Sachen, aber ich vermute, die Vorreinigung Fixes in 6u14 können beheben das Problem Sie sehen. Natürlich könnte ich das gleiche sagen über 6u18 Klasse Entladen Bugs. Wie ich schon sagte, ich bin kein Experte auf der GC Zeug.

Es gibt Fehlerbehebungen für:

  • 6u10: (betrifft 6u4 +) CMS löscht nie referents wenn -XX: + ParallelRefProcEnabled
  • 6u12: CMS: falsche Kodierung von flogenen Objekt-Arrays während der gleichzeitigen Vorreinigung
  • 6u12: CMS: falscher Überlauf Handling beim parallel gleichzeitigen Verwendung von Markierung
  • 6u14: CMS: Assertionsfehler "is_cms_thread == Thema :: current () -> is_ConcurrentGC_thread ()"
  • 6u14: CMS: Need CMSInitiatingPermOccupancyFraction für Perm, von CMSInitiatingOccupancyFraction divorcing
  • 6u14: CMS assert: _concurrent_iteration_safe_limit Update verpasst
  • 6u14: CMS: falsche Überlauf Handhabung bei der Vorreinigung von Referenzlisten
  • 6u14: SIGSEGV oder Behauptung (! Is_null (v), "oop-Wert kann nie Null sein"), wenn sie mit CMS und Coops läuft
  • 6u14: CMS:. Livelock in CompactibleFreeListSpace :: block_size ()
  • 6u14: Machen Sie CMS Arbeit mit Druck oops
  • 6u18: CMS: Core-Dump mit -XX: + UseCompressedOops
  • 6u18: CMS: Bugs Klasse Entladen im Zusammenhang
  • 6u18: CMS: ReduceInitialCardMarks unsicher in Gegenwart von cms Vorreinigung
  • 6u18: [Regression] -XX: NewRatio mit -XX: + UseConcMarkSweepGC verursacht fatale Fehler
  • 6u20: Kartenmarkierungen können zu lange aufgeschoben werden,

Zusätzlich zu allen oben genannten, 6u14 auch die G1 Garbage Collector, obwohl es noch in dem Test ist. G1 soll CMS in Java 7 ersetzen.

G1 kann in Java verwendet wird 6u14 und ein neuere Version mit den folgenden Befehlszeilenoptionen:

-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC

Ich würde mit etwas beginnen, viel einfacher, wie:

-server -Xms3072m -Xmx3072m -XX:+UseParallelOldGC -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps 

Und sehen, ob diese Ihren Bedürfnissen entspricht.

Es sieht aus wie Sie Objekte sind Gebäude, in dem Punkt zurück zu ihren Besitzern (A Punkte zu B Punkten zu A). Daraus ergibt sich die Referenzzähler verbleibenden größer als Null ist, so dass der Garbage Collector sie nicht bereinigen kann. Sie müssen den Zyklus brechen, wenn Sie sie loslassen. Annullieren des Referenz in entweder A oder B wird das Problem lösen. Dies funktioniert auch in größerer Referenz sieht aus wie (A -> B -> C -> D -> A). Vektoren und Objekt-Arrays können von Ihrem HashMaps verwendet werden.

Die presense des entfernten Lader kann einen Fehler zu bereinigen zeigen und schließen Verweise auf Objekte über JNDI oder andere Remote-Zugriffsverfahren geladen.

EDIT: Ich nahm einen zweiten Blick auf die letzte Zeile. Möglicherweise möchten Sie die Dauerwelle Zuordnung erhöhen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top