Java.lang.OutOfMemoryError: dépassement de la limite supérieure de la CG

j'obtiens 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 fractionner 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é, un OutOfMemoryError sera jeté.".

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

  • augmentation de la taille du tas, via "- Xmx1024m "(ou plus), ou
  • Disabling the error check totally, via "- XX: - UseGCOverheadLimit".

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

alors, question: y a-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, tout comme les données stockées dans HashMap! :- )

la question est également abordée dans un sujet connexe dans StackOverflow.

309
demandé sur Community 2011-04-30 07:49:33

16 réponses

vous êtes essentiellement à court de mémoire pour exécuter le processus en douceur. Options qui viennent à l'esprit:

  1. spécifiez plus de mémoire comme vous l'avez mentionné, essayez quelque chose comme -Xmx512m premier
  2. travailler avec des lots plus petits d'objets HashMap à traiter immédiatement si possible
  3. si vous avez beaucoup de chaînes en double, utilisez String.intern() avant de les mettre dans le HashMap
  4. utilisez le HashMap(int initialCapacity, float loadFactor) le constructeur à accorder pour votre cas
155
répondu WhiteFang34 2013-02-05 06:22:24

ce qui suit a fonctionné pour moi. Il suffit d'ajouter 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
répondu 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 tu dis que tu as 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 @ ceci document

40
répondu qupera 2016-08-17 16:35:25

pour info, on a 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 le ramassage des ordures, ce qui a fait disparaître le problème.

23
répondu takrl 2013-03-27 16:07:21

Ummm... vous aurez besoin de:

  1. " complètement repenser votre algorithme et les structures de données, de sorte qu'il n'a pas besoin de tous ces petits Hachmaps.

  2. créer une façade qui vous permet de page ces HashMaps Dans et hors de la mémoire comme nécessaire. Un simple LRU-cache pourrait être juste le billet.

  3. la mémoire de la JVM. Si nécessaire, même acheter 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 fan des solutions" plus de matériel", surtout si une solution algorithmique alternative peut être élaboré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.

de Quoi êtes-vous en fait en essayant de le faire de toute façon? Je pense qu'il y a une meilleure façon d'aborder votre vrai problème.

11
répondu corlettk 2013-07-27 15:08:37

Utilisation alternative HashMap mise en œuvre ( Trésor ). Java HashMap Standard a une mémoire supérieure à 12x. On peut lire les détails ici .

9
répondu dir 2013-01-17 17:19:25

ne conservez pas toute la structure en mémoire en attendant la fin.

écrire des résultats intermédiaires à une table temporaire dans la base de données au lieu de hashmaps - fonctionnellement, une table de base de données est l'équivalent d'un hashmap, c'est-à-dire que les deux supportent l'accès aux données par clavier, mais la table n'est pas liée à la mémoire, donc utilisez une table indexée ici plutôt que les hashmaps.

si 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 une méthode put(clé, valeur) et get(clé) comme une hashmap.

lorsque la table intermédiaire est complète, générer la(les) Instruction (s) sql requise (s) à partir de celle-ci plutôt que de la mémoire.

9
répondu Rodney P. Barbati 2013-01-28 19:07:28

le collecteur parallèle lancera un OutOfMemoryError si trop de temps est consacré à la collecte des ordures. En particulier, si plus de 98% du temps total est consacré à la collecte des ordures et si moins de 2% du tas est récupéré, OutOfMemoryError sera jeté. Cette fonctionnalité est conçue pour empêcher les applications de fonctionner pendant une période prolongée tout en faisant peu ou pas de progrès parce que le tas est trop petit. Si nécessaire, cette fonctionnalité peut être désactivée en ajoutant l'option -XX:-UseGCOverheadLimit à la ligne de commande.

8
répondu user3405305 2015-03-25 05:51:42

si vous créez des centaines de milliers de cartes hash, vous utilisez probablement beaucoup plus que ce dont vous avez réellement besoin; à moins que vous ne travailliez avec de grands fichiers ou des graphiques, 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
répondu RétroX 2011-04-30 04:04:10

si vous avez java8 , et que vous pouvez utiliser le collecteur D'ordures G1 , alors exécutez votre application avec:

 -XX:+UseG1GC -XX:+UseStringDeduplication

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 vers cette chaîne en mémoire.

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

plus d'informations sur:

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

5
répondu George C 2016-08-12 14:04:15

réparer 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 suivantes, Utiliser G1GC , qui dépense 10% sur la collecte des ordures contrairement à 2% dans les autres algorithmes de GC.

mis à part la mise de mémoire tas avec -Xms1g -Xmx2g , try '

-XX:+UseG1GC 
-XX:G1HeapRegionSize=n, 
-XX:MaxGCPauseMillis=m, 
-XX:ParallelGCThreads=n, 
-XX:ConcGCThreads=n`

regarder oracle article pour affiner ces paramètres.

Quelques question par rapport à l'G1GC en SOI:

Java 7 (JDK 7) collecte des ordures et documentation sur G1

Java G1 collecte des ordures dans la production de

stratégie Agressive de collecte des ordures

3
répondu Ravindra babu 2017-05-23 11:54:50

En cas d'erreur:

"erreur Interne du compilateur: java.lang.OutOfMemoryError: limite de charge de GC dépassée à java.lang.AbstractStringBuilder "

augmenter l'espace java heap à 2 Go i.e., -Xmx2g.

2
répondu 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
répondu shashi 2016-04-15 07:28:38

pour cette utilisation code ci-dessous dans votre fichier app gradle sous android closure.

dexOptions { javaMaxHeapSize " 4g" }

2
répondu Abhinandan Chada 2017-02-24 09:41:00

pour mon cas l'augmentation de la mémoire en utilisant -Xmx option é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 dans la colonne RES de la commande top a atteint la valeur définie dans l'option-Xmx. Puis en augmentant la mémoire en utilisant l'option -Xmx tout s'est bien passé.

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

1
répondu M. Mashaye 2015-12-15 18:09:20

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

0
répondu kanaparthikiran 2012-12-07 16:13:07