La façon de traiter avec "java.lang.OutOfMemoryError: Java heap space " erreur (taille de tas de 64 Mo) )
j'écris une application côté client Swing (graphical font designer) sur Java 5 . Récemment, je suis dans l'erreur java.lang.OutOfMemoryError: Java heap space
parce que je ne suis pas conservateur sur l'utilisation de la mémoire. L'utilisateur peut ouvrir un nombre illimité de fichiers, et le programme garde les objets ouverts dans la mémoire. Après une recherche rapide, j'ai trouvé ergonomie dans la Machine virtuelle Java 5.0 et d'autres disant sur Windows machine la JVM par défaut, la taille max de tas est 64MB
.
étant donné cette situation, comment devrais-je faire face à cette contrainte?
je pourrais augmenter la taille Max tas en utilisant ligne de commande option de java, mais cela nécessiterait de comprendre la RAM disponible et d'écrire un programme de lancement ou script. En outre, augmenter à un certain max fini ne se débarrasse pas finalement de la question.
je pourrais réécrire certains de mes codes pour persister objets au système de fichier fréquemment (en utilisant la base de données est la même chose) pour libérer la mémoire. Ça pourrait marcher, mais c'est probablement beaucoup de travail aussi.
si vous pouviez m'indiquer les détails des idées ci-dessus ou quelques alternatives comme mémoire virtuelle automatique, extension de la taille du tas dynamiquement , ce sera génial.
18 réponses
finalement, vous avez toujours un max fini de tas à utiliser peu importe quelle plate-forme vous êtes en cours d'exécution. Dans Windows 32 bit, cela représente environ 2 Go (pas spécifiquement tas, mais quantité totale de mémoire par processus). Il arrive juste que Java choisisse de rendre la valeur par défaut plus petite (probablement pour que le programmeur ne puisse pas créer des programmes qui ont une allocation de mémoire à la dérive sans se heurter à ce problème et avoir à examiner exactement ce qu'ils font).
donc ceci donné il y a plusieurs approches que vous pouvez prendre pour déterminer quelle quantité de mémoire vous avez besoin ou pour réduire la quantité de mémoire que vous utilisez. Une erreur courante avec les langages collectés comme Java ou C# est de conserver des 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 tas car le collecteur de déchets ne les supprimera pas.
dans ce cas, vous pouvez utiliser un profileur de mémoire Java pour déterminer quelles méthodes dans votre programme attribuent un grand nombre d'objets et ensuite déterminer s'il y a un moyen de s'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 attribuez ces objets pour une raison et vous devez garder autour références (selon ce que vous faites cela pourrait être le cas), vous aurez juste besoin d'augmenter la taille max tas lorsque vous démarrez le programme. Cependant, une fois que vous avez fait le profilage de la mémoire et que vous avez compris 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 quantité limitée de mémoire (peut-être en fonction de la taille de l'entrée), vous rencontrerez toujours ce problème. Ce n'est qu'après avoir épuisé tout cela que vous aurez besoin de regarder dans la mise en cache des objets vers le disque, etc. À ce stade, vous devriez avoir une très bonne raison de dire "j'ai besoin de XGB de mémoire" pour quelque chose et vous ne pouvez pas travailler autour de lui en améliorant vos algorithmes ou les modèles d'allocation de mémoire. En général, ce 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) et puis des techniques comme la mise en cache et la mémoire cartographiée IO deviennent utiles.
exécute Java avec l'option en ligne de commande -Xmx
, qui définit la taille maximum du tas.
vous pouvez spécifier par projet combien d'espace de tas votre projet veut
pour Eclipse Helios / Juno/Kepler :
clic droit de la souris sur
Run As - Run Configuration - Arguments - Vm Arguments,
puis Ajouter
-Xmx2048m
l'Augmentation de la taille du tas n'est pas une "solution", il est un "plâtre", 100% temporaire. Il va se planter à nouveau dans un autre endroit. Pour éviter ces problèmes, écrivez du code de haute performance.
- utilisez des variables locales dans la mesure du possible.
- assurez-vous de sélectionner l'objet approprié (EX: sélection entre String, StringBuffer et StringBuilder)
- utilisez un bon système de code pour votre programme(EX: utilisation de variables statiques VS non statiques variables)
- autre chose qui pourrait fonctionner sur votre code.
- Essayez de déplacer avec multy THREADING
grande mise en garde ---- à mon bureau, nous avons constaté que (sur certaines machines windows) nous ne pouvions pas allouer plus de 512m pour Java heap. Cela s'est avéré être dû au produit Anti-virus Kaspersky installé sur certaines de ces machines. Après avoir désinstallé ce produit AV, nous avons trouvé que nous pouvions allouer au moins 1,6 Go, I. e, - Xmx1600m (m est obligatoire sinon cela conduira à une autre erreur "trop petit amas initial") fonctionne.
aucune idée si cela se produit avec D'autres AV produits mais probablement cela se produit parce que le programme AV réserve un petit bloc de mémoire dans chaque espace d'adresse, empêchant ainsi une seule allocation vraiment grande.
VM argument a fonctionné pour moi dans eclipse. Si vous utilisez eclipse version 3.4, faites ce qui suit
passer à Run --> Run Configurations -->
puis sélectionner le projet sous Maven build --> puis sélectionner l'onglet" JRE "-- > puis entrer -Xmx1024m
.
alternativement vous pouvez faire Run --> Run Configurations --> select the "JRE" tab -->
puis entrer - Xmx1024m
cela devrait augmenter le tas de mémoire pour toutes les constructions/projets. La taille de mémoire ci-dessus est de 1 Go. Vous pouvez optimiser la vous voulez.
Oui, avec -Xmx vous pouvez configurer plus de mémoire pour votre JVM. Pour être sûr que vous n'avez pas de fuite ou de la mémoire des déchets. Prenez un tas dump et utilisez L'Analyseur de mémoire Eclipse pour analyser votre consommation de mémoire.
je voudrais ajouter des recommandations à partir d'oracle "151910920 de" dépannage article
Exception dans thread thread_name: java.lang.OutOfMemoryError: Java heap space
le message de détail Java heap space indique que l'objet N'a pas pu être attribué dans le Java heap. Cette erreur n'implique pas nécessairement une fuite de mémoire
Possible causes:
-
problème de configuration Simple , lorsque la taille de tas spécifiée est insuffisante pour l'application.
-
L'Application contient involontairement des références à des objets , ce qui empêche la collecte des ordures.
-
usage excessif de les finaliseurs .
une autre source potentielle de cette erreur se produit avec les applications qui font un usage excessif de finaliseurs. Si une classe a une méthode de finition, alors les objets de ce type n'ont pas leur espace récupéré au moment de la collecte des ordures
après collecte des ordures , les objets sont mis en file d'attente pour finalisation , qui se produit à une date ultérieure. finaliseurs sont exécutés par un thread de démon qui sert la file d'attente de finalisation. Si le finalizer thread ne peut pas suivre la file d'attente de finalisation, alors le tas de Java pourrait remplir et ce type de OutOfMemoryError exception serait jeté.
un scénario qui peut causer cette situation est quand une application crée threads de haute priorité qui font que la file d'attente finalisation augmente à une vitesse qui est plus rapide que la vitesse à laquelle le thread finalizer sert cette file d'attente.
suivre les étapes suivantes:
-
ouvert catalina.sh de tomcat / bin.
-
chnage JAVA_OPTS to
JAVA_OPTS="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms1536m -Xmx1536m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+DisableExplicitGC"
-
redémarrez votre tomcat
j'ai lu ailleurs que vous pouvez essayer - attraper java.lang.OutOfMemoryError et sur le bloc catch, vous pouvez libérer toutes les ressources que vous savez pourrait utiliser beaucoup de mémoire, des connexions étroites et ainsi de suite, puis faire un système.gc () puis réessayez ce que vous alliez faire.
une autre façon est celle-ci, bien que, je ne sais pas si cela fonctionnerait, mais je suis en train de tester si cela fonctionnera sur mon application.
L'idée est de faire des ordures collecte par système d'appel.gc () qui est connu pour augmenter la mémoire libre. Vous pouvez continuer à vérifier cela après l'exécution d'un code de gobage de mémoire.
//Mimimum acceptable free memory you think your app needs
long minRunningMemory = (1024*1024);
Runtime runtime = Runtime.getRuntime();
if(runtime.freeMemory()<minRunningMemory)
System.gc();
j'ai affronté le même problème de taille java tas. J'ai deux solutions si vous utilisez java 5(1.5).
1er: - il suffit d'installer jdk1.6 et allez dans les préférences d'eclipse et définissez le chemin jre de jav1 1.6 comme vous l'avez installé.
2e:-Vérifier votre VM argument et le laisser être ce qu'il est. juste ajouter une ligne en dessous de tous les arguments présents dans VM arguments -Xms512m-Xmx512m-XX:MaxPermSize=...m (192m).
je crois va travailler...
manière facile de résoudre OutOfMemoryError
en java est d'augmenter la taille maximale de tas en utilisant les options JVM -Xmx512M
, cela résoudra immédiatement votre OutOfMemoryError. C'est ma solution préférée quand je sors OutOfMemoryError dans Eclipse, Maven ou ANT tout en construisant projet parce que basé sur la taille du projet, vous pouvez facilement manquer de mémoire.
voici un exemple d'augmentation de la taille maximale de tas de JVM, aussi il est préférable de garder-Xmx à-XMS ration soit 1:1 ou 1: 1.5 Si vous définissez la taille du tas dans votre application java.
export JVM_ARGS="-Xms1024m -Xmx1024m"
si vous avez besoin de surveiller votre utilisation de la mémoire à l'exécution, le java.lang.le paquet de gestion offre des moyens qui peuvent être utilisés pour surveiller les pools de mémoire dans votre VM (par exemple, espace eden, génération tenure etc), et aussi le comportement de collecte des ordures.
l'espace libre en tas rapporté par ces MBeans variera grandement en fonction du comportement GC, particulièrement si votre application génère beaucoup d'objets qui sont ensuite GC-ed. Une approche possible consiste à surveiller les espace de tas après chaque GC complet, que vous pouvez être en mesure d'utiliser pour prendre une décision sur la libération de la mémoire par les objets persistants.
en fin de compte, votre meilleur pari est de limiter votre rétention de mémoire autant que possible tant que la performance reste acceptable. Comme un commentaire précédent a noté, la mémoire est toujours limitée, mais votre application devrait avoir une stratégie pour traiter l'épuisement de la mémoire.
notez que si vous avez besoin de cela dans une situation de déploiement, envisagez D'utiliser Java WebStart (avec une version "ondisk", pas la version réseau possible en Java 6u10 et plus tard) car il vous permet de spécifier les différents arguments à la JVM d'une manière multiplateforme.
sinon vous aurez besoin d'un lanceur spécifique au système d'exploitation qui définit les arguments dont vous avez besoin.
par défaut pour le développement JVM utilise petite taille et petite configuration pour d'autres caractéristiques liées à la performance. Mais pour la production, vous pouvez ajuster par exemple (en plus de cela, la configuration spécifique au serveur D'Application it peut exister) - > (S'il n'y a toujours pas assez de mémoire pour satisfaire la requête et que le tas a déjà atteint la taille maximale, une OutOfMemoryError se produira)
-Xms<size> set initial Java heap size
-Xmx<size> set maximum Java heap size
-Xss<size> set java thread stack size
-XX:ParallelGCThreads=8
-XX:+CMSClassUnloadingEnabled
-XX:InitiatingHeapOccupancyPercent=70
-XX:+UnlockDiagnosticVMOptions
-XX:+UseConcMarkSweepGC
-Xms512m
-Xmx8192m
-XX:MaxPermSize=256m (in java 8 optional)
par exemple: sur la plate-forme linux pour le mode de production 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 setenv.sh fichier sur folder / opt / tomcat/ bin /
touch /opt/tomcat/bin/setenv.sh
2.Ouvrez et écrivez ces paramètres pour définir le mode préférable.
nano /opt/tomcat/bin/setenv.sh
export CATALINA_OPTS="$CATALINA_OPTS -XX:ParallelGCThreads=8"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+CMSClassUnloadingEnabled"
export CATALINA_OPTS="$CATALINA_OPTS -XX:InitiatingHeapOccupancyPercent=70"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UnlockDiagnosticVMOptions"
export CATALINA_OPTS="$CATALINA_OPTS -XX:+UseConcMarkSweepGC"
export CATALINA_OPTS="$CATALINA_OPTS -Xms512m"
export CATALINA_OPTS="$CATALINA_OPTS -Xmx8192m"
export CATALINA_OPTS="$CATALINA_OPTS -XX:MaxMetaspaceSize=256M"
3. service tomcat restart
notez que la JVM utilise plus de mémoire que juste le tas. Exemple Les méthodes Java, Les piles de thread et les poignées natives sont allouées en mémoire séparé du tas, ainsi que des structures de données internes de JVM.
si vous continuez à allouer et à conserver des références à l'objet, vous remplirez n'importe quel ammontage de mémoire que vous avez.
une option est de faire une fermeture de fichier transparente et ouvrir quand ils changent d'onglet (vous ne gardez qu'un pointeur vers le fichier, et quand l'utilisateur change d'onglet, vous fermez et nettoyez tous les objets... ça ralentira le changement de fichier... mais...), et peut-être garder seulement 3 ou 4 fichiers en mémoire.
autre chose que vous devez faire est, lorsque l'utilisateur ouvre un fichier, charger, et intercepter tout OutOfMemoryError, puis (comme il n'est pas possible d'ouvrir le fichier) fermer le fichier, nettoyer ses objets et d'avertir l'utilisateur qu'il doit fermer les fichiers inutilisés.
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, donc vous devriez être prudent et gérer les problèmes de mémoire (ou au moins, être prudent avec eux).
quelques indices que j'ai vu avec des fuites de mémoire est:
-- > gardez à l'esprit que si vous mettez quelque chose dans une collection et ensuite l'oubliez, vous avez toujours une forte référence à elle, donc annuler la collection, nettoyer ou faire quelque chose avec elle... si pas, vous trouverez une fuite de mémoire difficile à trouver.
--> Peut-être, à l'aide de collections avec des références faibles (weakhashmap...) peut aider avec les problèmes de mémoire, mais vous doit être prudent avec elle, car vous pourriez trouver que l'objet vous recherchez a été recueilli.
-- > une autre idée que j'ai trouvée est de développer une collection persistante qui stocke 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...
en ce qui concerne netbeans, vous pouvez définir la taille Max tas pour résoudre le problème. Tout d'abord, allez dans "Exécuter", puis --> 'Projet de Configuration' --> 'Personnaliser' --> 'exécuter' de sa fenêtre surgi --> 'VM Option' --> remplir '-Xms2048m -Xmx2048m'.
si cette question se pose dans Wildfly 8 et JDK1.8, puis nous devons spécifier les paramètres MaxMetaSpace au lieu des paramètres PermGen.
par exemple, nous devons ajouter ci-dessous la configuration setenv.sh dossier de sauvagine.
JAVA_OPTS="$JAVA_OPTS -XX:MaxMetaspaceSize=256M"
pour plus d'information, veuillez cocher Wildfly Heap Issue