J'écris une application Swing côté client (concepteur de polices graphiques) sur Java 5 . Récemment, je rencontre une java.lang.OutOfMemoryError: Java heap space
erreur car je ne suis pas conservateur sur l'utilisation de la mémoire. L'utilisateur peut ouvrir un nombre illimité de fichiers et le programme conserve les objets ouverts en mémoire. Après une recherche rapide, j'ai trouvé l' ergonomie dans la machine virtuelle Java 5.0 et d'autres disant sur la machine Windows que la taille maximale du tas par défaut de la JVM était 64MB
.
Face à cette situation, comment gérer cette contrainte?
Je pourrais augmenter la taille maximale du tas en utilisant l' option de ligne de commande pour Java, mais cela nécessiterait de déterminer la RAM disponible et d'écrire un programme ou un script de lancement. De plus, augmenter jusqu'à un maximum fini ne résout pas finalement le problème.
Je pourrais réécrire une partie de mon code pour conserver fréquemment des objets dans le système de fichiers (utiliser la base de données est la même chose) pour libérer de la mémoire. Cela pourrait fonctionner, mais c'est probablement beaucoup de travail aussi.
Si vous pouviez me signaler les détails des idées ci-dessus ou certaines alternatives comme la mémoire virtuelle automatique, l'extension dynamique de la taille du segment de mémoire , ce serait parfait.
la source
Réponses:
En fin de compte, vous avez toujours un maximum fini de tas à utiliser, quelle que soit la plateforme sur laquelle vous exécutez. Dans Windows 32 bits, c'est autour
2GB
(pas spécifiquement le tas mais la quantité totale de mémoire par processus). Il se trouve que Java choisit de réduire la valeur par défaut (probablement pour que le programmeur ne puisse pas créer de programmes qui ont une allocation de mémoire incontrôlable sans se heurter à ce problème et sans avoir à examiner exactement ce qu'ils font).Donc, cela étant donné, vous pouvez adopter plusieurs approches pour déterminer la quantité de mémoire dont vous avez besoin ou pour réduire la quantité de mémoire que vous utilisez. Une erreur courante avec les langages récupérés comme Java ou C # est de conserver les références aux objets que vous n'utilisez plus ou d'allouer de nombreux objets lorsque vous pouvez les réutiliser à la place. Tant que les objets ont une référence à eux, ils continueront à utiliser l'espace de tas car le garbage collector ne les supprimera pas.
Dans ce cas, vous pouvez utiliser un profileur de mémoire Java pour déterminer quelles méthodes de votre programme allouent un grand nombre d'objets, puis déterminer s'il existe un moyen de vous assurer qu'ils ne sont plus référencés ou de ne pas les allouer en premier lieu. Une option que j'ai utilisée dans le passé est "JMP" http://www.khelekore.org/jmp/ .
Si vous déterminez que vous allouez ces objets pour une raison et que vous devez conserver les références (selon ce que vous faites, cela peut être le cas), vous n'aurez qu'à augmenter la taille maximale du tas lorsque vous démarrez le programme. Cependant, une fois que vous effectuez le profilage de la mémoire et comprenez comment vos objets sont alloués, vous devriez avoir une meilleure idée de la quantité de mémoire dont vous avez besoin.
En général, si vous ne pouvez pas garantir que votre programme fonctionnera dans une certaine quantité de mémoire (peut-être en fonction de la taille d'entrée), vous rencontrerez toujours ce problème. Ce n'est qu'après avoir épuisé tout cela que vous devrez étudier la mise en cache des objets sur le disque, etc. vos algorithmes ou modèles d'allocation de mémoire. En général, cela ne sera généralement le cas que pour les algorithmes fonctionnant sur de grands ensembles de données (comme une base de données ou un programme d'analyse scientifique), puis des techniques telles que la mise en cache et les entrées-sorties mappées en mémoire deviennent utiles.
la source
Exécutez Java avec l'option de ligne de commande
-Xmx
, qui définit la taille maximale du tas.Voir ici pour plus de détails .
la source
Vous pouvez spécifier par projet combien d'espace de stockage votre projet veut
Ce qui suit est pour Eclipse Helios / Juno / Kepler :
Clic droit de la souris sur
puis ajoutez ceci
la source
Augmenter la taille du tas n'est pas un "correctif", c'est un "plâtre", 100% temporaire. Il se plantera à nouveau ailleurs. Pour éviter ces problèmes, écrivez du code haute performance.
la source
Grande mise en garde ---- dans mon bureau, nous constations que (sur certaines machines Windows) nous ne pouvions pas allouer plus de 512 m pour le tas Java. Cela s'est avéré être dû au produit antivirus Kaspersky installé sur certaines de ces machines. Après avoir désinstallé ce produit AV, nous avons constaté que nous pouvions allouer au moins 1,6 Go, c'est-à-dire que
-Xmx1600m
(m est obligatoire , sinon cela conduira à une autre erreur "Trop petit tas initial").Aucune idée si cela se produit avec d'autres produits AV, mais cela se produit probablement parce que le programme AV réserve un petit bloc de mémoire dans chaque espace d'adressage, empêchant ainsi une seule allocation vraiment importante.
la source
Les arguments VM ont fonctionné pour moi dans Eclipse. Si vous utilisez la version 3.4 d'éclipse, procédez comme suit
allez dans
Run --> Run Configurations -->
puis sélectionnez le projet sous maven build -> puis sélectionnez l'onglet "JRE" -> puis entrez-Xmx1024m
.Sinon, vous pouvez faire
Run --> Run Configurations --> select the "JRE" tab -->
ensuite entrer -Xmx1024m
Cela devrait augmenter le tas de mémoire pour tous les builds / projets. La taille de mémoire ci-dessus est de 1 Go. Vous pouvez optimiser la façon dont vous le souhaitez.
la source
Oui,
-Xmx
vous pouvez configurer plus de mémoire pour votre JVM. Pour être sûr de ne pas fuir ni perdre de mémoire. Faites un vidage de tas et utilisez l'analyseur de mémoire Eclipse pour analyser votre consommation de mémoire.la source
Je voudrais ajouter des recommandations de dépannage Oracle article de .
Exception dans le thread thread_name: java.lang.OutOfMemoryError: Java heap space
Causes possibles:
Problème de configuration simple , où la taille de segment de mémoire spécifiée est insuffisante pour l'application.
L'application contient involontairement des références à des objets , ce qui empêche les objets d'être récupérés.
Utilisation excessive de finaliseurs .
Après le garbage collection , les objets sont mis en file d'attente pour la finalisation , qui se produit ultérieurement. les finaliseurs sont exécutés par un thread démon qui dessert la file d'attente de finalisation. Si le thread du finaliseur ne peut pas suivre la file d'attente de finalisation, le tas Java pourrait se remplir et ce type d' exception OutOfMemoryError serait levé .
Un scénario qui peut provoquer cette situation est lorsqu'une application crée des threads de haute priorité qui provoquent l' augmentation de la file d'attente de finalisation à une vitesse plus rapide que la vitesse à laquelle le thread du finaliseur traite cette file d'attente.
la source
Suivez les étapes ci-dessous:
Ouvert
catalina.sh
depuis tomcat / bin.Remplacez JAVA_OPTS par
Redémarrez votre tomcat
la source
J'ai lu ailleurs que vous pouvez essayer - attrapez java.lang.OutOfMemoryError et sur le bloc catch, vous pouvez libérer toutes les ressources que vous savez utiliser beaucoup de mémoire, fermer les connexions et ainsi de suite, puis faire une
System.gc()
nouvelle tentative tu allais faire.Une autre façon est la suivante, même si je ne sais pas si cela fonctionnerait, mais je teste actuellement si cela fonctionnera sur mon application.
L'idée est de faire la récupération de place en appelant System.gc () qui est connu pour augmenter la mémoire libre. Vous pouvez continuer à vérifier cela après l'exécution d'un code avalant de la mémoire.
la source
Un moyen simple de résoudre
OutOfMemoryError
en java consiste à augmenter la taille maximale du segment de mémoire en utilisant les options JVM-Xmx512M
, cela résoudra immédiatement votre OutOfMemoryError. C'est ma solution préférée lorsque j'obtiens OutOfMemoryError dans Eclipse, Maven ou ANT lors de la construction du projet, car en fonction de la taille du projet, vous pouvez facilement manquer de mémoire.Voici un exemple d'augmentation de la taille maximale du segment de mémoire de la machine virtuelle Java. Il est également préférable de conserver le rapport -Xmx à -Xms soit 1: 1 ou 1: 1,5 si vous définissez la taille de segment dans votre application java.
export JVM_ARGS="-Xms1024m -Xmx1024m"
Lien de référence
la source
Par défaut pour le développement, la JVM utilise une petite taille et une petite configuration pour d'autres fonctionnalités liées aux performances. Mais pour la production, vous pouvez régler par exemple (en plus, il peut exister une configuration spécifique à Application Server) -> (S'il n'y a toujours pas assez de mémoire pour satisfaire la demande et que le tas a déjà atteint la taille maximale, une OutOfMemoryError se produira)
Par exemple: Sur la plate-forme linux pour le mode de production, les paramètres préférables.
Après avoir téléchargé et configuré le serveur de cette façon http://www.ehowstuff.com/how-to-install-and-setup-apache-tomcat-8-on-centos-7-1-rhel-7/
1.créer le fichier setenv.sh dans le dossier / opt / tomcat / bin /
2.Ouvrez et écrivez ces paramètres pour définir le mode préférable.
3.
service tomcat restart
la source
J'ai rencontré le même problème de taille de tas java.
J'ai deux solutions si vous utilisez Java 5 (1.5).
installez simplement jdk1.6 et allez dans les préférences d'éclipse et définissez le chemin jre de jav1 1.6 comme vous l'avez installé.
Vérifiez votre argument VM et laissez-le être quel qu'il soit. ajoutez simplement une ligne ci-dessous de tous les arguments présents dans les arguments de la machine virtuelle comme -Xms512m -Xmx512m -XX: MaxPermSize = ... m (192m).
Je pense que cela va fonctionner...
la source
Si vous avez besoin de surveiller votre utilisation de la mémoire au moment de l'exécution, le
java.lang.management
package proposeMBeans
qui peut être utilisé pour surveiller les pools de mémoire dans votre machine virtuelle (par exemple, l'espace eden, la génération sécurisée, etc.), ainsi que le comportement de récupération de place.L'espace de mémoire libre signalé par ces MBeans variera considérablement en fonction du comportement du GC, en particulier si votre application génère un grand nombre d'objets qui seront ultérieurement édités par le GC. Une approche possible consiste à surveiller l'espace de tas libre après chaque GC complet, que vous pourrez peut-être utiliser pour prendre une décision sur la libération de mémoire par des objets persistants.
En fin de compte, votre meilleur pari est de limiter autant que possible votre rétention de mémoire tandis que les performances restent acceptables. Comme indiqué précédemment, la mémoire est toujours limitée, mais votre application doit avoir une stratégie pour gérer l'épuisement de la mémoire.
la source
Notez que si vous en avez besoin dans une situation de déploiement, envisagez d'utiliser Java WebStart (avec une version "ondisk", pas la version réseau - possible dans Java 6u10 et versions ultérieures) car cela vous permet de spécifier les différents arguments de la JVM en croix façon plate-forme.
Sinon, vous aurez besoin d'un lanceur spécifique au système d'exploitation qui définit les arguments dont vous avez besoin.
la source
Si ce problème se produit dans Wildfly 8 et JDK1.8, nous devons alors spécifier les paramètres MaxMetaSpace au lieu des paramètres PermGen.
Par exemple, nous devons ajouter la configuration ci-dessous dans le fichier setenv.sh de wildfly.
JAVA_OPTS="$JAVA_OPTS -XX:MaxMetaspaceSize=256M"
Pour plus d'informations, veuillez consulter Wildfly Heap Issue
la source
En ce qui concerne les netbeans, vous pouvez définir la taille maximale du tas pour résoudre le problème.
Allez dans 'Exécuter', puis -> 'Définir la configuration du projet' -> 'Personnaliser' -> 'exécuter' de sa fenêtre contextuelle -> 'Option VM' -> remplissez '-Xms2048m -Xmx2048m' .
la source
Si vous continuez à allouer et à conserver des références à un objet, vous remplirez toute la quantité de mémoire dont vous disposez.
Une option consiste à fermer et ouvrir un fichier transparent lorsqu'il change d'onglet (vous ne gardez qu'un pointeur sur le fichier, et lorsque l'utilisateur change d'onglet, vous fermez et nettoyez tous les objets ... cela rendra le changement de fichier plus lent ... mais ...), et peut-être ne garder que 3 ou 4 fichiers en mémoire.
Une autre chose que vous devez faire est, lorsque l'utilisateur ouvre un fichier, le charger et intercepter toute OutOfMemoryError, puis (comme il n'est pas possible d'ouvrir le fichier) fermer ce fichier, nettoyer ses objets et avertir l'utilisateur qu'il doit fermer inutilisé des dossiers.
Votre idée d'étendre dynamiquement la mémoire virtuelle ne résout pas le problème, car la machine est limitée sur les ressources, vous devez donc être prudent et gérer les problèmes de mémoire (ou du moins, soyez prudent avec eux).
Voici quelques conseils que j'ai vus avec les fuites de mémoire:
-> Gardez à l'esprit que si vous mettez quelque chose dans une collection et que vous l'oubliez ensuite, vous y avez toujours une référence forte, alors annulez la collection, nettoyez-la ou faites-en quelque chose ... sinon, vous trouverez un fuite de mémoire difficile à trouver.
-> Peut-être, l'utilisation de collections avec des références faibles (faiblessehashmap ...) peut aider avec des problèmes de mémoire, mais vous devez être prudent avec cela, car vous pourriez constater que l'objet que vous recherchez a été collecté.
-> Une autre idée que j'ai trouvée est de développer une collection persistante stockée sur les objets de base de données les moins utilisés et chargés de manière transparente. Ce serait probablement la meilleure approche ...
la source
Si tout le reste échoue, en plus d'augmenter la taille maximale du tas, essayez également d'augmenter la taille du swap. Pour Linux, à partir de maintenant, les instructions pertinentes peuvent être trouvées dans https://linuxize.com/post/create-a-linux-swap-file/ .
Cela peut être utile si vous compilez par exemple quelque chose de grand dans une plate-forme embarquée.
la source