Question

Quelle est la meilleure façon de déboguer exceptions java.lang.OutOfMemoryError?

Lorsque cela se produit à notre application, notre serveur d'applications (Weblogic) génère un fichier de vidage de tas. Faut-il utiliser le fichier de vidage de tas? Faut-il générer un thread dump Java? Quelle est exactement la différence?


Mise à jour: Quelle est la meilleure façon de générer des décharges de fil? Est-kill -3 (nos pistes d'applications sur Solaris) la meilleure façon de tuer l'application et générer une décharge de fil? Y at-il un moyen de générer la décharge de fil, mais pas tuer l'application?

Était-ce utile?

La solution

L'analyse et la fixation hors-mémoire des erreurs en Java est très simple.

En Java, les objets qui occupent la mémoire sont tous liés à d'autres objets, formant un arbre géant. L'idée est de trouver les plus grandes branches de l'arbre, qui pointe habituellement sur une situation de fuite de mémoire (en Java, vous fuite de mémoire pas lorsque vous oubliez de supprimer un objet, mais quand vous oubliez d'oublier l'objet, à savoir vous garder un référence à quelque part).

Étape 1. Activer tas décharges au moment de l'exécution

Exécuter votre processus avec -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp

(Il est sûr d'avoir ces options toujours activées. Ajustez le chemin au besoin, il doit être accessible en écriture par l'utilisateur java)

Étape 2. Reproduisez l'erreur

Laissez le d'application jusqu'à ce que le OutOfMemoryError se produit.

La machine virtuelle Java inscrira automatiquement un fichier comme java_pid12345.hprof.

Étape 3. Récupérer la décharge

Copie java_pid12345.hprof à votre PC (il sera au moins aussi grand que votre taille de tas maximale, peut donc être assez grand - gzip si nécessaire)

.

Étape 4. Ouvrez le fichier de vidage avec IBM Heap Analyzer ou Eclipse de mémoire Analyseur

L'analyseur Heap vous présentera un arbre de tous les objets qui étaient vivants au moment de l'erreur. Il y a des chances qu'il vous pointer directement au problème quand il ouvre.

Note: donner suffisamment de mémoire HeapAnalyzer, car il a besoin de charger votre dump ensemble

java -Xmx10g -jar ha456.jar

Étape 5. Identifier les zones de la plus grande utilisation tas

Parcourez l'arborescence d'objets et d'identifier des objets qui sont conservés autour inutilement.

Remarque il peut aussi arriver que tous des objets sont nécessaires, ce qui voudrait dire que vous avez besoin d'un tas plus grand. Taille et Réglage le tas appropriée.

Étape 6. Fixer votre code

Assurez-vous de ne garder que les objets autour que vous avez réellement besoin. Supprimer les éléments de collections en temps opportun. Assurez-vous de ne pas garder les références à des objets qui ne sont plus nécessaires, alors seulement peuvent-ils être des déchets collectés.

Autres conseils

J'ai eu du succès en utilisant une combinaison de Eclipse Memory Analyzer (MAT) et Java VM visuelle pour analyser les décharges tas. MAT a des rapports que vous pouvez exécuter qui vous donnent une idée générale de l'endroit où concentrer vos efforts dans votre code. VisualVM a une meilleure interface (à mon avis) pour inspecter réellement le contenu des différents objets que vous êtes intéressé à examiner. Il dispose d'un filtre où vous pouvez avoir afficher toutes les instances d'une classe particulière et voir où ils sont référencés et ce qu'ils se font référence. Il a été un moment que je l'ai utilisé deux outils pour cela, ils peuvent avoir un ensemble de fonctionnalités plus maintenant. Au moment utilisant à la fois a bien fonctionné pour moi.

Il est généralement très difficile de débogage des problèmes de OutOfMemoryError. Je vous recommande d'utiliser un outil de profilage. JProfiler fonctionne assez bien. Je l'ai utilisé dans le passé et il peut être très utile, mais je suis sûr qu'il y en a d'autres qui sont au moins aussi bon.

Pour répondre à vos questions spécifiques:

La décharge de A est une vue complète de l'ensemble du tas, à savoir tous les objets qui ont été créés avec new. Si vous êtes à court de mémoire, alors ce sera assez grand. Il vous indique le nombre de chaque type d'objet que vous avez.

A montre de vidage de fil que vous la pile pour chaque thread, vous montrant où dans le code chaque fil est au moment de la décharge. Rappelez-vous que un thread aurait pu causer la machine virtuelle Java pour exécuter de mémoire, mais il pourrait être un autre thread qui lance effectivement l'erreur. Par exemple, le fil 1 alloue un tableau d'octets qui remplit tout l'espace de segment de mémoire disponible, alors le thread 2 tente d'allouer un réseau de 1 octet et renvoie une erreur.

Vous pouvez également utiliser jmap / jhat pour attacher à un processus Java en cours d'exécution. Ces (famille) sont des outils très utiles si vous devez déboguer une application en cours d'exécution en direct.

Vous pouvez également laisser jmap en cours d'exécution comme la journalisation des tâches cron dans un fichier que vous pouvez analyser plus tard (Il est quelque chose que nous avons trouvé utile de déboguer une fuite de mémoire vive)

jmap -histo:live <pid> | head -n <top N things to look for> > <output.log>

Jmap peut également être utilisé pour générer une décharge de tas en utilisant l'option -dump qui peut être lu par le jhat.

Voir le lien suivant pour plus de détails http: //www.lshift .net / blog / 2006/03/08 / java-mémoire de profilage avec-jmap-et-jhat

Voici un autre lien vers un signet http://java.sun.com/developer/technicalArticles/J2SE/monitoring/

  

Quelle est la meilleure façon de déboguer exceptions java.lang.OutOfMemoryError?

Le OutOfMemoryError décrit le type d'erreur dans la description du message. Vous devez vérifier la description du message d'erreur pour gérer l'exception.

Il existe différentes causes profondes pour des exceptions à la mémoire. Reportez-vous à la documentation oracle pour plus de détails .

java.lang.OutOfMemoryError: Java heap space:

Cause . Le message de détail l'espace de Java indique objet ne peut pas être attribué dans le tas Java

java.lang.OutOfMemoryError: GC Overhead limit exceeded:

Cause: Le message de détail "GC limite les frais généraux dépassé" indique que le garbage collector est en cours d'exécution tout le temps et le programme Java progresse très lent

java.lang.OutOfMemoryError: Requested array size exceeds VM limit:

Car : Le message de détail « taille du tableau demandée dépasse la limite VM » indique que l'application (ou API utilisées par cette application) ont tenté d'attribuer un tableau qui est plus grande que la taille de segment

java.lang.OutOfMemoryError: Metaspace:

Cause: Java métadonnées de classe (les machines virtuelles de présentation interne de la classe Java) est allouée en mémoire native (appelée ici metaspace)

java.lang.OutOfMemoryError: request size bytes for reason. Out of swap space?:

Cause: Le message de détail "taille de la requête octets pour des raisons Sur l'espace d'échange.?" semble être une exception OutOfMemoryError. Cependant, le code Java HotSpot VM signale cette exception apparente lorsqu'une allocation du tas natif a échoué et le tas natif pourrait être proche de l'épuisement

java.lang.OutOfMemoryError: Compressed class space

Cause: Sur les plates-formes 64 bits à un pointeur de métadonnées de classe peuvent être représentés par un décalage de 32 bits (avec UseCompressedOops). Ceci est contrôlé par la ligne de commande UseCompressedClassPointers de drapeau (par défaut).

Si le UseCompressedClassPointers est utilisé, la quantité d'espace disponible pour les métadonnées de classe est fixé au montant CompressedClassSpaceSize. Si l'espace nécessaire pour UseCompressedClassPointers dépasse CompressedClassSpaceSize, un java.lang.OutOfMemoryError avec des détails espace de classe comprimé est levée.

Note: Il y a plus d'un type de métadonnées classe - Klass métadonnées et autres métadonnées. Seules les métadonnées Klass sont stockées dans l'espace délimité par CompressedClassSpaceSize. Les autres métadonnées sont stockées dans Metaspace.

  

Faut-il utiliser le fichier de vidage de tas? Faut-il générer un thread dump Java? Quelle est exactement la différence?

Oui. Vous pouvez utiliser ce fichier de vidage de tas tas pour déboguer le problème en utilisant des outils de profilage comme visualvm ou mat Vous pouvez utiliser dump de fil pour obtenir un meilleur aperçu sur l'état des discussions.

Reportez-vous à cette question SE de connaître les differenes:

Différence entre javacore, vidage de fil et décharge tas dans Websphere

  

Quelle est la meilleure façon de générer des décharges de fil? Est-kill -3 (notre application se exécute sur Solaris) la meilleure façon de tuer l'application et générer une décharge de fil? Y at-il un moyen de générer la décharge de fil, mais pas tuer l'application?

kill -3 <process_id> génère thread dump et cette commande ne tue pas processus java.

Une fois que vous obtenez un outil pour regarder à la décharge de tas, regard à tout fil qui était dans l'état en cours dans la pile de fil. Son probablement l'un de ceux qui a obtenu l'erreur. Parfois, la décharge de tas vous dire ce fil avait le droit d'erreur en haut.

Que vous doit pointer dans la bonne direction. Ensuite, utiliser des techniques de débogage standard (journalisation, débogueur, etc.) à se concentrer sur le problème. Utilisez la classe Runtime pour obtenir l'utilisation actuelle de la mémoire et l'enregistrer comme méthode ou processus exécute question.

J'utilise généralement Memory Analyzer Eclipse. Il affiche les coupables présumés (les objets qui occupent la majeure partie de la décharge de tas) et différentes hiérarchies d'appel qui génère ces objets. Une fois que la cartographie est là, nous pouvons revenir au code et essayer de comprendre s'il y a une mémoire possible fuite ne importe où dans le chemin de code.

Cependant, OOM ne signifie pas toujours qu'il ya une fuite de mémoire. Il est toujours possible que la mémoire nécessaire par une application pendant l'état stable ou en charge ne sont pas disponibles dans le matériel / VM. Par exemple, il pourrait y avoir un processus Java 32 bits (mémoire max utilisé ~ 4 Go) alors que la machine virtuelle est à seulement 3 Go. Dans ce cas, d'abord l'application peut fonctionner très bien, mais OOM peut être rencontré au fur et à l'exigence de mémoire approche 3Go.

Comme mentionné par d'autres, la capture décharge de fil ne sont pas coûteux, mais la capture dump du tas est. J'ai observé que lors de la capture de l'application tas décharge (en général) se fige et seulement tuer suivie par le redémarrage aide à récupérer.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top