Ich erhalte diese Fehlermeldung, wenn ich meine JUnit
Tests:
java.lang.OutOfMemoryError: GC overhead limit exceeded
Ich weiß, was ein OutOfMemoryError
ist, aber was bedeutet die GC-Overhead-Grenze? Wie kann ich das lösen?
Ich erhalte diese Fehlermeldung, wenn ich meine JUnit
Tests:
java.lang.OutOfMemoryError: GC overhead limit exceeded
Ich weiß, was ein OutOfMemoryError
ist, aber was bedeutet die GC-Overhead-Grenze? Wie kann ich das lösen?
Diese Meldung bedeutet, dass der Garbage Collector aus irgendeinem Grund übermäßig viel Zeit benötigt (standardmäßig 98 % der gesamten CPU-Zeit des Prozesses) und bei jedem Durchlauf nur sehr wenig Speicher zurückgewinnt (standardmäßig 2 % des Heaps).
Das bedeutet, dass Ihr Programm keinen Fortschritt mehr macht und die ganze Zeit nur noch mit der Garbage Collection beschäftigt ist.
Um zu verhindern, dass Ihre Anwendung CPU-Zeit in Anspruch nimmt, ohne etwas zu tun, wirft die JVM diese Error
damit Sie eine Chance haben, das Problem zu diagnostizieren.
Die seltenen Fälle, in denen ich dies gesehen habe, ist, wo einige Code Tonnen von temporären Objekten und Tonnen von schwach referenzierten Objekten in einer bereits sehr Speicher-begrenzten Umgebung erstellt wurde.
Sehen Sie sich den Java GC tuning guide an, der für verschiedene Java-Versionen verfügbar ist und Abschnitte zu diesem speziellen Problem enthält:
Wäre es richtig, Ihre Antwort wie folgt zusammenzufassen? "Es ist genau wie ein 'Out of Java Heap space'-Fehler. Geben Sie ihm mit -Xmx mehr Speicher." ?
@Tim: Nein, das wäre nicht korrekt. Auch wenn man ihm mehr Speicher gibt könnte Wenn Sie das Problem reduzieren wollen, sollten Sie sich auch Ihren Code ansehen und herausfinden, warum er diese Menge an Speicherplatz produziert und warum Ihr Code knapp unter der "Out of Memory"-Marke vorbeischrammt. Das ist oft ein Zeichen für fehlerhaften Code.
Danke, es scheint, dass Oracle nicht wirklich gut in der Datenmigration ist, sie haben die Verbindung unterbrochen.
Zitat aus dem Artikel von Oracle "Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning" :
Übermäßige GC-Zeit und OutOfMemoryError
Der parallele Kollektor gibt einen OutOfMemoryError aus, wenn zu viel Zeit mit der Garbage Collection verbracht wird: Wenn mehr als 98% der Gesamtzeit mit der Garbage Collection verbracht wird und weniger als 2% des Heaps wiederhergestellt werden, wird ein OutOfMemoryError ausgegeben. Mit dieser Funktion soll verhindert werden, dass Anwendungen über einen längeren Zeitraum laufen, aber keine oder nur geringe Fortschritte machen, weil der Heap zu klein ist. Falls erforderlich, kann diese Funktion durch Hinzufügen der Option
-XX:-UseGCOverheadLimit
in die Befehlszeile.
EDIT: Sieht so aus, als könnte jemand schneller tippen als ich :)
"Sie können dies ausschalten...", aber der OP sollte dies höchstwahrscheinlich nicht tun.
Können Sie mir den Unterschied zwischen "-XX" und "-Xmx" erklären? Ich konnte sie auch mit der Option "-Xmx" ausschalten.
Ich antworte hier auf einen sehr alten Kommentar, aber... @Bart Der -XX:
am Anfang mehrerer Befehlszeilenoptionen ist eine Art Flagge, die anzeigt, dass diese Option in hohem Maße VM-spezifisch und instabil ist (und sich in zukünftigen Versionen ohne Ankündigung ändern kann). In jedem Fall ist die -XX:-UseGCOverheadLimit
Flag weist die VM an, die Überprüfung des GC-Overhead-Limits zu deaktivieren (tatsächlich "auszuschalten"), während Ihr -Xmx
hat lediglich den Haufen vergrößert. Im letzteren Fall war die Überprüfung des GC-Overheads immer noch läuft Es hört sich so an, als ob ein größerer Heap die GC-Thrashing-Probleme gelöst hätte. in Ihrem Fall (dies ist nicht immer hilfreich).
Wenn Sie sicher sind, dass es keine Speicherlecks in Ihrem Programm, versuchen Sie es:
-Xmx1g
.-XX:+UseConcMarkSweepGC
.Erforderlichenfalls kann die Grenzwertprüfung kann durch Hinzufügen der folgenden Option deaktiviert werden -XX:-UseGCOverheadLimit
in die Befehlszeile.
Normalerweise ist es der Code. Hier ist ein einfaches Beispiel:
import java.util.*;
public class GarbageCollector {
public static void main(String... args) {
System.out.printf("Testing...%n");
List<Double> list = new ArrayList<Double>();
for (int outer = 0; outer < 10000; outer++) {
// list = new ArrayList<Double>(10000); // BAD
// list = new ArrayList<Double>(); // WORSE
list.clear(); // BETTER
for (int inner = 0; inner < 10000; inner++) {
list.add(Math.random());
}
if (outer % 1000 == 0) {
System.out.printf("Outer loop at %d%n", outer);
}
}
System.out.printf("Done.%n");
}
}
Verwendung von Java 1.6.0_24-b07 auf einem Windows 7 32 bit.
java -Xloggc:gc.log GarbageCollector
Dann schauen Sie sich gc.log
Zugegeben, das ist nicht der beste Test oder das beste Design, aber wenn man mit einer Situation konfrontiert ist, in der man keine andere Wahl hat, als eine solche Schleife zu implementieren, oder wenn man mit bestehendem Code zu tun hat, der sich schlecht verhält, kann die Entscheidung, Objekte wiederzuverwenden, anstatt neue zu erstellen, die Anzahl der Fälle reduzieren, in denen der Garbage Collector in die Quere kommt.
Bitte klären Sie: Wenn Sie sagen, "n-mal ausgelöst", bedeutet das, dass eine reguläre GC n-mal passiert, oder dass der "GC-Overhead-Limit überschritten" Fehler von der OP berichtet n-mal passiert?
Ich testete gerade jetzt mit Java 1.8.0_91 und bekam nie einen Fehler/Ausnahme, und die "Triggered n-mal" wurde von Zählen der Anzahl der Zeilen in der gc.log
Datei. Meine Tests zeigen insgesamt viel weniger Zeiten, aber die wenigsten "Auslöser"-Zeiten für BETTER, und jetzt ist BAD "schlimmer" als WORST. Meine Zählungen: SCHLECHT: 26, SCHLECHTER: 22, BESSER 21.
Ursache für den Fehler nach der Java [8] Plattform, Standard Edition Anleitung zur Fehlerbehebung (Hervorhebung und Zeilenumbrüche hinzugefügt)
[...] "GC overhead limit exceeded" zeigt an, dass der Garbage Collector ständig läuft und das Java-Programm nur sehr langsam vorankommt.
Nach einer Garbage Collection, wenn die Java-Prozesse verbringen mehr als 98% ihrer Zeit mit der Garbage Collection und wenn es weniger als 2% des Heaps wiederherstellt und dies die letzten 5 (zur Kompilierzeit konstanten) aufeinanderfolgenden Garbage Collections getan hat, dann wird ein
java.lang.OutOfMemoryError
geworfen wird. [...]
Neben dem Setzen von Heap-Speicher mit - Xms1g -Xmx2g
, versuchen
-XX:+UseG1GC -XX:G1HeapRegionSize=n -XX:MaxGCPauseMillis=m
-XX:ParallelGCThreads=n -XX:ConcGCThreads=n
Sehen Sie sich einige weitere Fragen zu G1GC an
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
18 Stimmen
Das klingt sehr interessant. Ich würde mich freuen, wenn jemand einen Code posten könnte, der dies erzeugt.
2 Stimmen
Ich habe einfach das Problem gefunden, das zu einem zu hohen Speicherverbrauch in der Nähe der Grenze des Heaps führte. Eine einfache Lösung könnte sein, der Java-Engine einfach etwas mehr Heap-Speicher zu geben (-Xmx), aber das hilft nur, wenn die Anwendung genau so viel Speicher benötigt, wie das Heap-Limit vorher gesetzt war.
0 Stimmen
Besuchen Sie auch xmlandmore.blogspot.com/2011/05/
1 Stimmen
@Mnementh ich hatte eine Antwort hier gegeben überprüfen Sie, ob es hilft stackoverflow.com/questions/11091516/
16 Stimmen
@SimonKuang Beachten Sie, dass es mehrere
OutOfMemoryError
Szenarien, für die eine Vergrößerung des Heaps keine gültige Lösung ist: Wenn die Anzahl der nativen Threads nicht ausreicht und die Anzahl der perm gen (die vom Heap getrennt ist) nicht ausreicht, sind zwei Beispiele. Seien Sie vorsichtig mit allzu pauschalen Aussagen überOutOfMemoryErrors
Es gibt eine unerwartete Vielfalt an Ursachen für sie.3 Stimmen
Wie haben Sie das Problem gelöst?
2 Stimmen
Dieser Fehler geschah und geschieht immer noch für mich mit Jdk1.8.0_91
1 Stimmen
@Thorsten Niehues: Nun, ich habe das Problem im Wesentlichen durch die Verwendung von weniger Speicher gelöst. Wie die oberste Antwort zeigt, handelt es sich um eine Situation mit sehr wenig verbleibendem Speicher, während eine Menge temporärer Objekte erstellt wird. Im Grunde führt kein Weg daran vorbei, man muss die Speichernutzung reduzieren.
0 Stimmen
@Buhb Ich hatte gerade diesen Fehler bei Hadoop 3.2.0, als ich einen lokalen Auftrag (ohne Cluster) zum Sortieren von 28 GB Daten ausführte. Er funktionierte mehrere Stunden lang und explodierte mit diesem Fehler kurz vor dem Ende des Auftrags. Normalerweise wird dieser Datensatz mit dieser Map-Reduce-Aufgabe gut abgeschlossen.
1 Stimmen
Für zukünftige Besucher - Jede Antwort, die Ihnen einfach sagt, dass Sie die Heapgröße erhöhen sollen (suchen Sie nach
javaMaxHeapSize
oXmx
) könnte Ihr Problem lösen, wenn Sie mit dieser Menge an Daten arbeiten. Aber Sie müssen Ihren Code wirklich überprüfen, um die Datennutzung zu begrenzen. Versuchen Sie, eine kleinere Datenmenge abzufragen oder die zu verarbeitenden Datensätze zu begrenzen. Wenn Sie keine andere Möglichkeit haben, lassen Sie Ihren Code auf einem Rechner in der Cloud laufen, der Ihnen so viel Speicherplatz zur Verfügung stellen kann, wie Sie wollen.1 Stimmen
@smaug Maschinen in der Cloud sind immer noch irgendwo physische Computer. Jeder Typ, den Sie mieten können, hat eine bestimmte Menge an RAM. Eine weitere Überlegung ist, dass größere Maschinen viel mehr Geld kosten als kleinere.