Ich erhalte diese Fehlermeldung, wenn ich meine JUnit-Tests durchführe:
Java.lang.OutOfMemoryError: GC overhead limit exceeded
Ich weiß, was ein OutOfMemoryError
ist, aber was bedeutet GC-Overhead-Limit? Wie kann ich das lösen?
Diese Meldung bedeutet, dass der Garbage Collector aus irgendeinem Grund zu viel Zeit in Anspruch nimmt (standardmäßig 98% der gesamten CPU-Zeit des Prozesses) und in jedem Durchlauf nur sehr wenig Arbeitsspeicher wiederherstellt (standardmäßig 2% des Heapspeichers).
Dies bedeutet effektiv, dass Ihr Programm keine Fortschritte mehr macht und zu jeder Zeit nur die Garbage Collection ausführt.
Um zu verhindern, dass Ihre Anwendung die CPU-Zeit in Anspruch nimmt, ohne dass etwas getan wird, gibt die JVM dieses Error
aus, damit Sie die Möglichkeit haben, das Problem zu diagnostizieren.
In den seltenen Fällen, in denen ich dies erlebt habe, hat Code Tonnen temporärer Objekte und Tonnen Objekte mit schwachen Verweisen in einer Umgebung mit ohnehin sehr begrenztem Speicher erstellt.
Schauen Sie sich dieser Artikel für Details an (speziell dieser Teil ).
Der GC löst diese Ausnahme aus, wenn zu viel Zeit für die Speicherbereinigung aufgewendet wird, um eine zu geringe Rendite zu erzielen, z. 98% der CPU-Zeit wird für die GC aufgewendet und weniger als 2% des Heapspeichers werden wiederhergestellt.
Mit dieser Funktion soll verhindert werden, dass Anwendungen über einen längeren Zeitraum ausgeführt werden, während nur geringe oder gar keine Fortschritte erzielt werden, da der Heap zu klein ist.
Sie können dies mit der Befehlszeilenoption -XX:-UseGCOverheadLimit
deaktivieren.
Weitere Infos hier
EDIT: sieht so aus, als könnte jemand schneller tippen als ich :)
Wenn Sie sicher sind, dass in Ihrem Programm kein Speicherverlust vorhanden ist, versuchen Sie Folgendes:
-Xmx1g
.-XX:+UseConcMarkSweepGC
.Bei Bedarf kann die Grenzwertprüfung durch Hinzufügen der Option -XX:-UseGCOverheadLimit
zur Befehlszeile deaktiviert werden.
Es ist normalerweise 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");
}
}
Verwenden von Java 1.6.0_24-b07 Unter Windows7 32-Bit.
Java -Xloggc: gc.log GarbageCollector
Dann schauen Sie sich gc.log an
Dies ist zwar nicht der beste Test oder das beste Design, aber wenn Sie mit einer Situation konfrontiert sind, in der Sie keine andere Wahl haben, als eine solche Schleife zu implementieren, oder wenn Sie mit vorhandenem Code arbeiten, der sich schlecht verhält, kann die Entscheidung, Objekte wiederzuverwenden, anstatt neue zu erstellen, abnehmen wie oft der Müllmann im Weg ist ...
Ursache für den Fehler
"GC-Overhead-Limit überschritten" zeigt an, dass der Garbage Collector die ganze Zeit ausgeführt wird und das Programm Java nur sehr langsam Fortschritte macht.
Wenn der Java-Prozess nach einer Garbage Collection mehr als 98% seiner Zeit mit Garbage Collection verbringt und weniger als 2% des Heaps wiederherstellt und dies getan hat Bisher wurden die letzten 5 (Kompilierzeitkonstante) aufeinanderfolgenden Garbage-Collections geworfen, dann wurde ein Java.lang.OutOfMemoryError geworfen
Versuchen Sie es nicht nur mit -Xms1g -Xmx2g
, sondern auch mit dem Festlegen des Heapspeichers
-XX:+UseG1GC -XX:G1HeapRegionSize=n -XX:MaxGCPauseMillis=m
-XX:ParallelGCThreads=n -XX:ConcGCThreads=n
Schauen Sie sich einige verwandte Fragen zu G1GC an
Java 7 (JDK 7) Garbage Collection und Dokumentation zu G1
Erhöhen Sie einfach die Größe des Heapspeichers ein wenig, indem Sie diese Option aktivieren
Ausführen → Konfigurationen ausführen → Argumente → VM Argumente
-Xms1024M -Xmx2048M
Xms - für die minimale Grenze
Xmx - für maximales Limit
Für mich haben die folgenden Schritte funktioniert:
Eclipse.ini
Veränderung
-Xms40m
-Xmx512m
zu
-Xms512m
-Xmx1024m
Starten Sie Eclipse neu
Folgendes hat bei mir funktioniert. Fügen Sie einfach das folgende Snippet hinzu:
Android {
compileSdkVersion 25
buildToolsVersion '25.0.1'
defaultConfig {
applicationId "yourpackage"
minSdkVersion 10
targetSdkVersion 25
versionCode 1
versionName "1.0"
multiDexEnabled true
}
dexOptions {
javaMaxHeapSize "4g"
}
}
versuche dies
öffne die build.gradle
Datei
Android {
dexOptions {
javaMaxHeapSize = "4g"
}
}
erhöhen Sie javaMaxHeapsize in Ihrer build.gradle-Datei (Modul: App)
dexOptions {
javaMaxHeapSize "1g"
}
zu (Diese Zeile in Gradle einfügen)
dexOptions {
javaMaxHeapSize "4g"
}
Ein Neustart meines MacBook behebt dieses Problem für mich.
Sie können auch die Speicherzuordnung und die Größe des Heapspeichers erhöhen, indem Sie Folgendes zu Ihrer gradle.properties
-Datei hinzufügen:
org.gradle.jvmargs=-Xmx2048M -XX\:MaxHeapSize\=32g
Es muss nicht 2048M und 32g sein, machen Sie es so groß, wie Sie wollen.
Sie müssen die Speichergröße in Jdeveloper erhöhen. Gehen Sie zu setDomainEnv.cmd.
set WLS_HOME=%WL_HOME%\server
set XMS_Sun_64BIT=**256**
set XMS_Sun_32BIT=**256**
set XMX_Sun_64BIT=**3072**
set XMX_Sun_32BIT=**3072**
set XMS_JROCKIT_64BIT=**256**
set XMS_JROCKIT_32BIT=**256**
set XMX_JROCKIT_64BIT=**1024**
set XMX_JROCKIT_32BIT=**1024**
if "%Java_VENDOR%"=="Sun" (
set WLS_MEM_ARGS_64BIT=**-Xms256m -Xmx512m**
set WLS_MEM_ARGS_32BIT=**-Xms256m -Xmx512m**
) else (
set WLS_MEM_ARGS_64BIT=**-Xms512m -Xmx512m**
set WLS_MEM_ARGS_32BIT=**-Xms512m -Xmx512m**
)
und
set MEM_PERM_SIZE_64BIT=-XX:PermSize=**256m**
set MEM_PERM_SIZE_32BIT=-XX:PermSize=**256m**
if "%Java_USE_64BIT%"=="true" (
set MEM_PERM_SIZE=%MEM_PERM_SIZE_64BIT%
) else (
set MEM_PERM_SIZE=%MEM_PERM_SIZE_32BIT%
)
set MEM_MAX_PERM_SIZE_64BIT=-XX:MaxPermSize=**1024m**
set MEM_MAX_PERM_SIZE_32BIT=-XX:MaxPermSize=**1024m**
Ich arbeite in Android Studio und bin auf diesen Fehler gestoßen, als ich versucht habe, ein signiertes APK für die Veröffentlichung zu generieren. Ich konnte ein Debug-APK problemlos erstellen und testen, aber sobald ich ein Release-APK erstellen wollte, wurde der Erstellungsprozess minutenlang ausgeführt und schließlich mit dem Fehler "Java.lang.OutOfMemoryError: GC" beendet Gemeinkostenlimit überschritten ". Ich habe die Größe des Heapspeichers sowohl für den VM als auch für den Android DEX-Compiler erhöht, aber das Problem blieb bestehen. Schließlich stellte sich nach vielen Stunden und Tassen Kaffee heraus, dass das Problem in meiner "build.gradle" -Datei auf App-Ebene lag - ich hatte den Parameter "minifyEnabled" für den Release-Build-Typ auf "false" gesetzt, wodurch Proguard-Artikel ausgeführt wurden über Code, der den Code-Verkleinerungsprozess nicht durchlaufen hat (siehe https://developer.Android.com/studio/build/shrink-code.html ). Ich habe den Parameter 'minifyEnabled' in 'true' geändert und das Release Build wurde wie ein Traum ausgeführt :)
Kurz gesagt, ich musste meine "build.gradle" -Datei auf App-Ebene ändern von: // ...
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-Android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.sign_config_release
}
debug {
debuggable true
signingConfig signingConfigs.sign_config_debug
}
}
//...
zu
//...
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-Android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.sign_config_release
}
debug {
debuggable true
signingConfig signingConfigs.sign_config_debug
}
}
//...
Befolgen Sie die folgenden Anweisungen, um die Größe des Heapspeichers in IntelliJIDEA zu erhöhen. Es hat bei mir funktioniert.
Für Windows Benutzer
Gehen Sie zu dem Speicherort, an dem IDE installiert ist, und suchen Sie nach Folgendem.
idea64.exe.vmoptions
Bearbeiten Sie die Datei und fügen Sie Folgendes hinzu.
-Xms512m
-Xmx2024m
-XX:MaxPermSize=700m
-XX:ReservedCodeCacheSize=480m
Das ist es !!