it-swarm.com.de

Fehler Java.lang.OutOfMemoryError: GC-Overhead-Limit überschritten

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?

741
Mnementh

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 ).

713
Joachim Sauer

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 :)

198
dave

Wenn Sie sicher sind, dass in Ihrem Programm kein Speicherverlust vorhanden ist, versuchen Sie Folgendes:

  1. Erhöhen Sie die Größe des Heapspeichers, z. B. -Xmx1g.
  2. Aktivieren Sie den gleichzeitigen Low-Pausen-Collector -XX:+UseConcMarkSweepGC.
  3. Verwenden Sie vorhandene Objekte nach Möglichkeit erneut, um Speicherplatz zu sparen.

Bei Bedarf kann die Grenzwertprüfung durch Hinzufügen der Option -XX:-UseGCOverheadLimit zur Befehlszeile deaktiviert werden.

82

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

  • 444-mal mit der BAD-Methode ausgelöst
  • 666-mal mit der WORSE-Methode ausgelöst
  • 354-mal mit der BETTER-Methode ausgelöst

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 ...

41
Mike

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

  1. Erhöhen Sie die Größe des Heapspeichers , wenn der aktuelle Heapspeicher nicht ausreicht.
  2. Wenn dieser Fehler nach dem Erhöhen des Heapspeichers weiterhin auftritt, verwenden Sie Profilerstellungstools für den Arbeitsspeicher wie MAT (Speicheranalysetool), Visual VM etc und Speicherlecks beheben.
  3. Aktualisieren Sie die JDK-Version auf die neueste Version (1.8.x) oder mindestens 1.7.x und verwenden Sie den G1GC-Algorithmus. . Das Durchsatzziel für den G1 GC ist eine Anwendungszeit von 90 Prozent und eine Speicherbereinigungszeit von 10 Prozent.
  4. 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

Java G1 Garbage Collection in der Produktion

Oracle Technetwork-Artikel für das GC-Finetuning

31
Ravindra babu

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

27
chopss

Für mich haben die folgenden Schritte funktioniert:

  1. Öffnen Sie die Datei Eclipse.ini
  2. Veränderung

    -Xms40m
    -Xmx512m
    

    zu

    -Xms512m
    -Xmx1024m
    
  3. Starten Sie Eclipse neu

siehe hier

14

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"
    }
}
11
H.S.H

versuche dies

öffne die build.gradle Datei

  Android {
        dexOptions {
           javaMaxHeapSize = "4g"
        }
   }
11
alicanozkara

erhöhen Sie javaMaxHeapsize in Ihrer build.gradle-Datei (Modul: App)

dexOptions {
    javaMaxHeapSize "1g"
}

zu (Diese Zeile in Gradle einfügen)

 dexOptions {
        javaMaxHeapSize "4g"
    }
5
saigopi

Ein Neustart meines MacBook behebt dieses Problem für mich.

1
Thomas

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.

1
John Doe

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**
0
shashi

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
    }
}

//...
0

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 !!

0
Dulith De Costa