Java.lang.OutOfMemoryError: Limite de frais généraux du GC dépassée


Je reçois cette erreur dans un programme qui crée plusieurs (centaines de milliers) objets HashMap avec quelques (15-20) entrées de texte chacune. Ces chaînes doivent toutes être collectées (sans se décomposer en plus petites quantités) avant d'être soumises à une base de données.

Selon Sun, l'erreur se produit " si trop de temps est passé dans la collecte des ordures: si plus de 98% du temps total est passé dans la collecte des ordures et moins de 2% du tas est récupéré, une OutOfMemoryError sera levée.".

Apparemment, on pourrait utiliser la ligne de commande pour passer des arguments à la JVM pour

  • Augmenter la taille du tas, via "- Xmx1024m " (ou plus), ou
  • Désactivant complètement la vérification des erreurs, via "-XX:-UseGCOverheadLimit".

La première approche fonctionne bien, la seconde se termine dans un autre java.lang.OutOfMemoryError, cette fois sur le tas.

Donc, question: existe-t-il une alternative programmatique à cela, pour le cas d'utilisation particulier (c'est-à-dire, plusieurs petits objets HashMap)? Si j'utilise la méthode HashMap clear (), par exemple, le problème disparaît, mais les données stockées dans HashMap le font également! :-)

Le problème est également discuté dans un sujet lié à dans StackOverflow.

Author: Community, 2011-04-30

16 answers

Vous manquez essentiellement de mémoire pour exécuter le processus en douceur. Options qui viennent à l'esprit:

  1. Spécifier plus de mémoire, comme vous l'avez mentionné, essayez quelque chose entre les deux, comme -Xmx512m premier
  2. Travailler avec des lots plus petits d'objets HashMap à traiter en même temps si possible
  3. Si vous avez beaucoup de doubles cordes, l'utilisation String.intern() sur eux avant de les mettre dans le HashMap
  4. Utiliser le HashMap(int initialCapacity, float loadFactor) constructeur de tune pour votre cas,
 155
Author: WhiteFang34, 2013-02-05 06:22:24

Ce qui suit a fonctionné pour moi. Ajoutez simplement l'extrait suivant:

dexOptions {
        javaMaxHeapSize "4g"
}

À votre build.gradle:

android {
    compileSdkVersion 23
    buildToolsVersion '23.0.1'

    defaultConfig {
        applicationId "yourpackage"
        minSdkVersion 14
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"

        multiDexEnabled true
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    packagingOptions {

    }

    dexOptions {
        javaMaxHeapSize "4g"
    }
}
 59
Author: Mina Fawzy, 2016-02-23 14:01:28

@ takrl: Le paramètre par défaut pour cette option est:

java -XX:+UseConcMarkSweepGC

Ce qui signifie que cette option n'est pas active par défaut. Donc quand vous dites que vous avez utilisé l'option "+XX:UseConcMarkSweepGC" Je suppose que vous utilisiez cette syntaxe:

java -XX:+UseConcMarkSweepGC

Ce qui signifie que vous activiez explicitement cette option. Pour la syntaxe correcte et les paramètres par défaut de Java HotSpot VM Options @ this document

 40
Author: qupera, 2016-08-17 16:35:25

Pour mémoire, nous avons eu le même problème aujourd'hui. Nous l'avons corrigé en utilisant cette option:

-XX:-UseConcMarkSweepGC

Apparemment, cela a modifié la stratégie utilisée pour la collecte des ordures, ce qui a fait disparaître le problème.

 23
Author: takrl, 2013-03-27 16:07:21

{[0] }mM... vous devrez soit:

  1. Repensez complètement votre algorithme et vos structures de données, de sorte qu'il n'ait pas besoin de tous ces petits HashMaps.

  2. Créez une façade qui vous permet de mettre en page ces HashMaps dans et hors de la mémoire selon les besoins. Un simple LRU-cache pourrait être juste le ticket.

  3. Augmenter la mémoire disponible pour la JVM. Si nécessaire, même l'achat de plus de RAM pourrait être la solution la plus rapide et la MOINS CHÈRE, si vous avez la gestion de la machine qui héberge cette bête. Cela dit: je ne suis généralement pas un fan des solutions "jeter plus de matériel", surtout si une solution algorithmique alternative peut être imaginée dans un délai raisonnable. Si vous continuez à jeter plus de matériel à chacun de ces problèmes vous bientôt dans la loi des rendements décroissants.

Qu'essayez-vous réellement de faire de toute façon? Je soupçonne qu'il y a une meilleure approche de votre problème réel.

 11
Author: corlettk, 2013-07-27 15:08:37

Utilisez une implémentation alternative de HashMap (Trove ). Java HashMap standard a une surcharge de mémoire >12x. On peut lire les détails ici.

 9
Author: dir, 2013-01-17 17:19:25

Ne stockez pas toute la structure en mémoire en attendant d'arriver à la fin.

Write intermediate results to a temporary table in the database instead of hashmaps - fonctionnellement, une table de base de données est l'équivalent d'une hashmap, c'est-à-dire que les deux prennent en charge l'accès par clé aux données, mais la table n'est pas liée à la mémoire, utilisez donc une table indexée ici plutôt que les hashmaps.

Si cela est fait correctement, votre algorithme ne devrait même pas remarquer le changement-correctement ici signifie utiliser une classe pour représenter la table, même en lui donnant un put (clé, valeur) et une méthode get(clé) tout comme un hashmap.

Lorsque la table intermédiaire est terminée, générez les instructions sql requises à partir de celle-ci au lieu de la mémoire.

 9
Author: Rodney P. Barbati, 2013-01-28 19:07:28

Le collecteur parallèle lancera un OutOfMemoryError si trop de temps est passé dans la récupération de place. En particulier, si plus de 98% du temps total est consacré à la collecte des ordures et que moins de 2% du tas est récupéré, OutOfMemoryError sera jeté. 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. Si nécessaire, cette fonctionnalité peut être désactivée en ajoutant l'option -XX:-UseGCOverheadLimit à la commande ligne.

 8
Author: user3405305, 2015-03-25 05:51:42

Si vous créez des centaines de milliers de cartes de hachage, vous utilisez probablement beaucoup plus que ce dont vous avez réellement besoin; sauf si vous travaillez avec des fichiers ou des graphiques volumineux, le stockage de données simples ne devrait pas dépasser la limite de mémoire Java.

Vous devriez essayer de repenser votre algorithme. Dans ce cas, j'offrirais plus d'aide à ce sujet, mais je ne peux donner aucune information tant que vous n'en aurez pas plus sur le contexte du problème.

 5
Author: RétroX, 2011-04-30 04:04:10

Si vous avez java8, et vous pouvez utiliser le G1 Garbage Collector, puis exécutez votre application avec:

 -XX:+UseG1GC -XX:+UseStringDeduplication

Cela indique au G1 de trouver des chaînes similaires et de ne garder qu'une seule d'entre elles en mémoire, et les autres ne sont qu'un pointeur sur cette chaîne en mémoire.

Ceci est utile lorsque vous avez beaucoup de chaînes répétées. Cette solution peut ou non fonctionner et dépend de chaque application.

Plus d'infos on:
https://blog.codecentric.de/en/2014/08/string-deduplication-new-feature-java-8-update-20-2/ http://java-performance.info/java-string-deduplication/

 5
Author: George C, 2016-08-12 14:04:15

Corrigez les fuites de mémoire dans votre application à l'aide d'outils de profil comme eclipse MAT ou VisualVM

Avec JDK 1.7.x ou versions ultérieures, utilisez G1GC, qui dépense 10% sur la collecte des ordures contrairement à 2% dans d'autres algorithmes GC.

En dehors de la définition de 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 oeil à l'articleoracle pour affiner ces paramètres.

Une question liée à G1GC dans SE:

Java 7 (JDK 7) garbage collection et documentation sur G1

Java G1 collecte des ordures dans la production de

Stratégie agressive de garbage collector

 3
Author: Ravindra babu, 2017-05-23 11:54:50

En cas d'erreur:

"Erreur interne du compilateur: java.lang.OutOfMemoryError: Limite de surcharge du GC dépassée sur java.lang.AbstractStringBuilder"

Augmentez l'espace de tas java à 2 Go, c'est-à-dire -Xmx2g.

 2
Author: bpb, 2013-01-23 08:17:40

Vous devez augmenter la taille de la mémoire dans Jdeveloper aller à 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
)
and

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
 2
Author: shashi, 2016-04-15 07:28:38

Pour cette utilisation ci-dessous le code dans votre fichier gradle app sous la fermeture Android.

DexOptions { javaMaxHeapSize " 4g" }

 2
Author: Abhinandan Chada, 2017-02-24 09:41:00

Pour mon cas, augmenter la mémoire en utilisant l'option -Xmx était la solution.

J'ai eu un fichier 10g lu en java et chaque fois j'ai eu la même erreur. Cela s'est produit lorsque la valeur de la colonne RES de la commande top a atteint la valeur définie dans l'option-Xmx. Ensuite, en augmentant la mémoire en utilisant l'option -Xmx, tout s'est bien passé.

Il y avait aussi un autre point. Lorsque j'ai défini JAVA_OPTS ou CATALINA_OPTS dans mon compte utilisateur et augmenté à nouveau la quantité de mémoire, j'ai eu la même erreur. Ensuite, J' imprimé la valeur de ces variables d'environnement dans mon code, ce qui m'a donné des valeurs différentes de celles que j'ai définies. La raison en était que Tomcat était la racine de ce processus, puis comme je n'étais pas un su-doer, j'ai demandé à l'administrateur d'augmenter la mémoire dans catalina.sh dans Tomcat.

 1
Author: M. Mashaye, 2015-12-15 18:09:20

Cela m'a aidé à me débarrasser de cette erreur.Cette option désactive - XX: + DisableExplicitGC

 0
Author: kanaparthikiran, 2012-12-07 16:13:07