Je reçois ce message d'erreur lorsque j'exécute mes tests JUnit:
Java.lang.OutOfMemoryError: GC overhead limit exceeded
Je sais ce qu'est une OutOfMemoryError
, mais que signifie limite de temps système GC? Comment puis-je résoudre ça?
Ce message signifie que, pour une raison quelconque, le ramasse-miettes prend trop de temps (par défaut, 98% du temps CPU du processus) et récupère très peu de mémoire à chaque exécution (par défaut, 2% du tas).
Cela signifie effectivement que votre programme cesse de progresser et est occupé à exécuter uniquement le nettoyage de la mémoire à tout moment.
Pour empêcher votre application d’absorber le temps CPU sans rien faire, la machine virtuelle Java envoie cette variable Error
afin que vous puissiez diagnostiquer le problème.
Les rares cas où j'ai vu cela se produire sont ceux où du code créait des tonnes d'objets temporaires et des tonnes d'objets faiblement référencés dans un environnement déjà très contraint en mémoire.
Découvrez cet article pour plus de détails (spécifiquement cette partie ).
Le GC lève cette exception lorsque trop de temps est passé dans la récupération de place pour un retour trop faible, par exemple. 98% du temps processeur est consacré au CPG et moins de 2% du segment est récupéré.
Cette fonctionnalité est conçue pour empêcher les applications de s'exécuter pendant une période prolongée tout en faisant peu ou pas de progrès car le tas est trop petit.
Vous pouvez désactiver cette option avec l'option de ligne de commande -XX:-UseGCOverheadLimit
Plus d'infos ici
EDIT: on dirait que quelqu'un peut taper plus vite que moi :)
Si vous êtes sûr qu'il n'y a pas de fuite de mémoire dans votre programme, essayez de:
-Xmx1g
.-XX:+UseConcMarkSweepGC
.Si nécessaire, le limite peut être désactivé en ajoutant l'option -XX:-UseGCOverheadLimit
à la ligne de commande.
C'est généralement le code. Voici un exemple simple:
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");
}
}
Utilisation de Java 1.6.0_24-b07 Sous Windows7 32 bits.
Java -Xloggc: gc.log GarbageCollector
Alors regardez gc.log
Maintenant accordé, ce n’est pas le meilleur test ou la meilleure conception, mais face à une situation dans laquelle vous n’avez pas le choix de mettre en place une telle boucle ou lorsque vous traitez avec du code existant qui se comporte mal, choisir de réutiliser des objets plutôt que d’en créer de nouveaux peut réduire le nombre de fois où le ramasse-miettes se met en travers du chemin ...
Cause de la erreur
Limite de temps système GC dépassée "indique que le ramasse-miettes fonctionne tout le temps et que le programme Java progresse très lentement.
Après une récupération de place, si le processus Java passe plus de 98% de son temps environ dans cette tâche et s'il récupère moins de 2% du segment de mémoire et s'il le fait déjà jusqu’à présent, les 5 dernières collectes de mémoire consécutives (constante de temps de compilation) consécutives, puis un Java.lang.OutOfMemoryError est renvoyé.
En plus de définir la mémoire de tas avec -Xms1g -Xmx2g
, essayez
-XX:+UseG1GC -XX:G1HeapRegionSize=n -XX:MaxGCPauseMillis=m
-XX:ParallelGCThreads=n -XX:ConcGCThreads=n
Jetez un coup d'œil à d'autres questions connexes sur G1GC
récupération de place Java 7 (JDK 7) et documentation sur G1
ramasse-miettes Java G1 en production
article Oracle sur le technetwork pour l’ajustement fin du GC
Il suffit d’augmenter un peu la taille du tas en définissant cette option dans
Exécuter → Exécuter les configurations → Arguments → VM arguments
-Xms1024M -Xmx2048M
Xms - pour la limite minimale
Xmx - pour la limite maximale
Pour moi, les étapes suivantes ont fonctionné:
Eclipse.ini
Changement
-Xms40m
-Xmx512m
à
-Xms512m
-Xmx1024m
Redémarrer Eclipse
Ce qui suit a fonctionné pour moi. Ajoutez simplement l'extrait suivant:
Android {
compileSdkVersion 25
buildToolsVersion '25.0.1'
defaultConfig {
applicationId "yourpackage"
minSdkVersion 10
targetSdkVersion 25
versionCode 1
versionName "1.0"
multiDexEnabled true
}
dexOptions {
javaMaxHeapSize "4g"
}
}
essaye ça
ouvrez le fichier build.gradle
Android {
dexOptions {
javaMaxHeapSize = "4g"
}
}
augmenter javaMaxHeapsize dans votre fichier build.gradle (Module: app)
dexOptions {
javaMaxHeapSize "1g"
}
à (Ajouter cette ligne dans le titre)
dexOptions {
javaMaxHeapSize "4g"
}
Le redémarrage de mon MacBook a résolu ce problème pour moi.
Vous pouvez également augmenter l’allocation de mémoire et la taille de tas en ajoutant ceci à votre fichier gradle.properties
:
org.gradle.jvmargs=-Xmx2048M -XX\:MaxHeapSize\=32g
Il n'est pas nécessaire que ce soit 2048M et 32g, le rendre aussi grand que vous le souhaitez.
Vous devez augmenter la taille de la mémoire dans Jdeveloper. Allez à 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**
)
et
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**
Je travaille dans Android Studio et j'ai rencontré cette erreur en essayant de générer un fichier APK signé pour publication. J'ai été capable de construire et de tester un APK de débogage sans problème, mais dès que je voulais construire un APK de version, le processus de construction fonctionnait pendant des minutes et finissait par se terminer par le message "Erreur Java.lang.OutOfMemoryError: GC limite de dépassement dépassée ". J'ai augmenté la taille des segments de mémoire pour le compilateur VM et Android DEX, mais le problème persistait. Enfin, après de nombreuses heures et des tasses de café, il est apparu que le problème se trouvait dans mon fichier "build.gradle" au niveau de l'application. J'avais le paramètre 'minifyEnabled' pour le type de construction de la version défini sur 'false', ce qui a entraîné l'exécution de fichiers Proguard sur le code qui n'a pas encore subi le processus de réduction de code (voir https://developer.Android.com/studio/build/shrink-code.html ). J'ai remplacé le paramètre 'minifyEnabled' par 'true' et la compilation a été exécutée comme un rêve :)
En bref, je devais changer mon fichier 'build.gradle' au niveau de l'application à partir de: // ...
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
}
}
//...
à
//...
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
}
}
//...
Pour augmenter la taille de la mémoire dans IntelliJ IDEA, suivez les instructions suivantes. Cela a fonctionné pour moi.
Pour les utilisateurs Windows,
Accédez à l'emplacement où IDE est installé et recherchez les éléments suivants.
idea64.exe.vmoptions
Editez le fichier et ajoutez ce qui suit.
-Xms512m
-Xmx2024m
-XX:MaxPermSize=700m
-XX:ReservedCodeCacheSize=480m
C'est ça !!