GC-Overhead-Limit überschritten

93

Welche Abtastzeit verwendet JVM, um "java.lang.OutOfMemoryError: GC-Overhead-Limit überschritten" auszulösen? Ich weiß, dass Sie 98% und 2% mit den Parametern GCTimeLimit und GCHeapFreeLimit steuern können, aber wie lange dauert die Abtastung?

PRK
quelle

Antworten:

82

Von Java SE 6 HotSpot [tm] Optimierung der Garbage Collection für virtuelle Maschinen

folgende

Übermäßige GC-Zeit und OutOfMemoryError

Der gleichzeitige Kollektor löst einen OutOfMemoryError aus, wenn zu viel Zeit für die Speicherbereinigung aufgewendet wird: Wenn mehr als 98% der Gesamtzeit für die Speicherbereinigung aufgewendet werden und weniger als 2% des Heaps wiederhergestellt werden, wird ein OutOfMemoryError ausgelöst. Diese Funktion soll verhindern, dass Anwendungen über einen längeren Zeitraum ausgeführt werden, ohne dass Fortschritte erzielt werden, da der Heap zu klein ist. Bei Bedarf kann diese Funktion deaktiviert werden, indem der Befehlszeile die Option -XX: -UseGCOverheadLimit hinzugefügt wird.

Die Richtlinie ist dieselbe wie im Parallelkollektor, außer dass die Zeit, die für die Ausführung gleichzeitiger Sammlungen aufgewendet wird, nicht auf das Zeitlimit von 98% angerechnet wird. Mit anderen Worten, nur Sammlungen, die ausgeführt werden, während die Anwendung gestoppt ist, zählen zu einer übermäßigen GC-Zeit. Solche Sammlungen sind normalerweise auf einen Fehler im gleichzeitigen Modus oder eine explizite Sammlungsanforderung zurückzuführen (z. B. einen Aufruf von System.gc ()).

in Verbindung mit einer Passage weiter unten

Eine der am häufigsten anzutreffenden Anwendungen der expliziten Speicherbereinigung ist die verteilte Speicherbereinigung (DGC) mit RMIs. Anwendungen, die RMI verwenden, beziehen sich auf Objekte in anderen virtuellen Maschinen. In diesen verteilten Anwendungen kann kein Müll gesammelt werden, ohne gelegentlich den lokalen Heap zu sammeln. Daher erzwingt RMI regelmäßig vollständige Sammlungen. Die Häufigkeit dieser Sammlungen kann mit Eigenschaften gesteuert werden. Beispielsweise,

java -Dsun.rmi.dgc.client.gcInterval=3600000

-Dsun.rmi.dgc.server.gcInterval=3600000 Gibt die explizite Erfassung einmal pro Stunde anstelle der Standardrate von einmal pro Minute an. Dies kann jedoch auch dazu führen, dass die Wiederherstellung einiger Objekte viel länger dauert. Diese Eigenschaften können so hoch wie Long.MAX_VALUE eingestellt werden, um die Zeit zwischen expliziten Sammlungen effektiv unendlich zu machen, wenn keine Obergrenze für die Aktualität der DGC-Aktivität gewünscht wird.

Scheint zu implizieren, dass der Evaluierungszeitraum für die Bestimmung der 98% eine Minute lang ist, aber möglicherweise auf der JVM von Sun mit der richtigen Definition konfigurierbar ist.

Natürlich sind auch andere Interpretationen möglich.

Edwin Buck
quelle
5
Die verteilte RMI-Speicherbereinigung ist eine nicht mit der regulären Speicherbereinigung zusammenhängende Aktivität. Ich verstehe also nicht, wie Sie daraus schließen können, was Sie gerade getan haben.
Stephen C
2
Die Folgerung ist nicht perfekt oder sogar richtig, deshalb wird "scheint zu implizieren" anstelle von "impliziert" verwendet. Wenn Sie der Beobachtung zustimmen, dass, wenn die Leute bei Sun eine Minute zur Bestimmung des Speicherbereinigungsintervalls für RMI verwendet haben, diese Erfassungszeit bei gleichzeitiger Erfassung nur dann akkumuliert wird, wenn das Hauptprogramm angehalten wird, und einen kleinen Vertrauenssprung macht Dann stehen die Chancen gut, dass 98% innerhalb einer Minute gesammelt werden. Es ist eine magische Zahl, aber eine Minute ist eine magische Zahl, die häufig im Vergleich zu 3,5 Minuten verwendet wird.
Edwin Buck
@StephenC meinst du, auch wenn wir es einstellen -XX:+DisableExplicitGC , wird es keine Auswirkungen auf die RMI-bezogene Konfiguration haben und das System wird gc in der mit dem Parameter eingestellten Frequenz aufrufen-Dsun.rmi.dgc.server.gcInterval
Steephen
1
@Steephen - Nein. Das sage ich nicht. Ich spreche von dieser Aussage: "Scheint zu implizieren, dass der Bewertungszeitraum für die Bestimmung der 98% eine Minute lang ist ..." . Und beachten Sie, dass Edwin zustimmt, dass die Folgerung "unvollkommen" ist. Die Schlussfolgerung basiert auf der Annahme, dass die Sun-Leute, die RMI (& DGC) implementiert haben, in enger Kommunikation mit den Leuten standen, die den GC-Overhead-Limit-Mechanismus implementiert haben. Ich vermute, dass die beiden Entwicklungen tatsächlich zu unterschiedlichen Zeiten stattgefunden haben. Beachten Sie, dass die -Dsun.rmi.dgc.server.gcIntervalEigenschaft seit Java 1.2 vorhanden ist.
Stephen C
1
Ein besserer Ansatz, um die richtige Antwort auf diese Frage zu finden, wäre ein Blick auf den OpenJDK-Quellcode.
Stephen C