web-dev-qa-db-fra.com

java.lang.OutOfMemoryError: espace de pile Java

Je reçois l'erreur suivante lors de l'exécution d'un programme multi-threading

Java.lang.OutOfMemoryError: Java heap space

L'erreur ci-dessus s'est produite dans l'un des threads.

  1. Jusqu'à ma connaissance, l'espace de segment de mémoire est occupé uniquement par des variables d'instance. Si cela est correct, alors pourquoi cette erreur s'est produite après avoir fonctionné correctement pendant que l'espace est alloué pour les variables d'instance lors de la création de l'objet.

  2. Y at-il un moyen d'augmenter l'espace de tas?

  3. Quels changements dois-je apporter à mon programme pour qu'il prenne moins de place?

91
Yatendra Goel

Si vous souhaitez augmenter votre espace de mémoire, vous pouvez utiliser Java -Xms<initial heap size> -Xmx<maximum heap size> sur la ligne de commande. Par défaut, les valeurs sont basées sur la version de JRE et la configuration du système. Vous pouvez trouver plus d'informations sur les options VM sur le site Web Java }.

Cependant, je vous recommanderais de profiler votre application pour savoir pourquoi votre taille de segment de mémoire est mangée. NetBeans a un très bon profileur inclus. Je crois qu’il utilise le jvisualvm sous le capot. Avec un profileur, vous pouvez essayer de trouver où de nombreux objets sont créés, quand les objets sont ramassés, etc.

98
Thomas Owens

1.- Oui, mais cela renvoie assez à toute la mémoire utilisée par votre programme. 

2.- Oui, voir les options Java VM 

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size

C'est à dire 

Java -Xmx2g attribuer un maximum de 2 Go de RAM à votre application

Mais vous devriez voir si vous n'avez pas de fuite de mémoire en premier.

3.- Cela dépend du programme. Essayez des fuites de mémoire ponctuelles. Cette question serait difficile à répondre. Dernièrement, vous pouvez profiler en utilisant JConsole pour essayer de savoir où va votre mémoire 

25
OscarRyz

Vous pouvez consulter ce site pour en savoir plus sur la mémoire dans la machine virtuelle Java: http://developer.streamezzo.com/content/learn/articles/optimization-heap-memory-usage

J'ai trouvé utile d'utiliser visualgc pour observer le remplissage des différentes parties du modèle de mémoire afin de déterminer les modifications à apporter.

Il est difficile de déterminer quelle partie de la mémoire a été remplie, d’où visualgc, car vous voudrez peut-être simplement changer la partie qui pose un problème plutôt que de simplement dire: 

Bien! Je vais donner 1G de RAM à la JVM.

Essayez d’être plus précis sur ce que vous faites, à long terme, vous trouverez probablement le programme plus performant.

Pour déterminer où peut se trouver la fuite de mémoire, vous pouvez utiliser des tests unitaires à cet effet, en testant la quantité de mémoire utilisée avant et après le test, et si le changement est trop important, vous pouvez l'examiner, mais vous devez faites la vérification pendant que votre test est toujours en cours.

8
James Black

Pour augmenter la taille du tas, vous pouvez utiliser l'argument -Xmx lors du démarrage de Java. par exemple.

-Xmx256M
6
Adamski
  1. Jusqu'à ma connaissance, l'espace de segment de mémoire est occupé uniquement par des variables d'instance. Si cela est correct, cette erreur s’est produite après une exécution correcte de temps en temps, l’espace alloué aux instances d’instance étant alloué au moment de la création de l’objet.

Cela signifie que vous créez de façon continue plus d'objets dans votre application. Les nouveaux objets seront stockés dans la mémoire de tas et c’est la raison de la croissance de la mémoire de tas.

Heap ne contient pas seulement des variables d'instance. Il stockera tous les types de données non primitifs (Objets). La durée de vie de ces objets peut être courte (bloc de méthode) ou longue (jusqu'à ce que l'objet soit référencé dans votre application).

  1. Y at-il un moyen d'augmenter l'espace de tas?

Oui. Jetez un oeil à cet Oracle article pour plus de détails.

Il existe deux paramètres pour définir la taille du tas:

-Xms:, qui définit la taille de tas initiale et minimale

-Xmx:, qui définit la taille de tas maximale

  1. Quels changements dois-je apporter à mon programme pour qu'il prenne moins de place?

Cela dépend de votre application. 

  1. Définissez la mémoire de tas maximale selon les exigences de votre application

  2. Ne provoquez pas de fuites de mémoire dans votre application

  3. Si vous trouvez des fuites de mémoire dans votre application, recherchez la cause première à l'aide d'outils de profilage tels que MAT , Visual VM , jconsole etc Une fois que vous avez trouvé la cause, corrigez les fuites.

Notes importantes d'Oracle article

Cause: Le message de détail Espace de segment de mémoire Java indique que l'objet n'a pas pu être alloué dans le segment de mémoire Java. Cette erreur n'implique pas nécessairement une fuite de mémoire.

Raisons possibles:

  1. Configuration incorrecte (n'allouant pas de mémoire suffisante)
  2. L'application conserve involontairement des références à des objets, ce qui empêche leur récupération.
  3. Applications qui font un usage excessif de finaliseurs. Si une classe a une méthode finalize, l'espace des objets de ce type ne sera pas récupéré au moment de la récupération de place. Si le processus de finalisation ne peut pas suivre, avec la file d'attente de finalisation, le tas Java pourrait se remplir et ce type d'exception OutOfMemoryError serait levé

Sur une note différente, utilisez de meilleurs algorithmes de récupération de place (CMS ou G1GC)

Regardez cette question pour comprendre G1GC

6
Ravindra babu

Vous pouvez obtenir la taille de votre mémoire en dessous de programe.

public class GetHeapSize {
    public static void main(String[] args) {
        long heapsize = Runtime.getRuntime().totalMemory();
        System.out.println("heapsize is :: " + heapsize);
    }
} 

en conséquence, vous pouvez également augmenter la taille du tas en utilisant: Java -Xmx2g http://www.Oracle.com/technetwork/Java/javase/tech/vmoptions-jsp-140102.html

6
user2663609
  1. Dans la plupart des cas, le code n'est pas optimisé. Libérez les objets dont vous pensez qu'ils ne seront plus nécessaires. Évitez de créer des objets dans votre boucle à chaque fois. Essayez d'utiliser des caches. Je ne sais pas comment se porte votre application. Mais en programmation, une règle de la vie normale s’applique aussi

    Mieux vaut prévenir que guérir. "Ne créez pas d'objets inutiles"

5
DKSRathore
  1. Les variables locales sont situées sur la pile. L'espace de tas est occupé par des objets.

  2. Vous pouvez utiliser l'option -Xmx.

  3. Fondamentalement, l'espace mémoire est utilisé chaque fois que vous allouez un nouvel objet avec new et libéré un certain temps après que l'objet n'est plus référencé. Veillez donc à ne pas conserver de références à des objets dont vous n’avez plus besoin.

3
sepp2k

Non, je pense que vous pensez à la pile. L'espace de tas est occupé par des objets. La façon de l'augmenter est -Xmx256m, en remplaçant le 256 par le montant dont vous avez besoin sur la ligne de commande.

1
Yishai

Pour éviter cette exception, si vous utilisez JUnit et Spring, ajoutez-le à chaque classe de test:

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
0
Aliuk

Dans Netbeans, allez dans la barre d’outils 'Exécuter', -> 'Définir la configuration du projet' -> 'Personnaliser' -> 'Exécuter' de sa fenêtre contextuelle -> 'Option de VM' -> Remplissez '-Xms2048m -Xmx2048m '. Cela pourrait résoudre le problème de la taille du tas.

0
Xiaogang