Comment surveiller l'utilisation de la mémoire Java?


Nous avons une application j2ee en cours d'exécution sur Jboss et nous voulons surveiller son utilisation de la mémoire. Actuellement, nous utilisons le code suivant

    System.gc();
    Runtime rt = Runtime.getRuntime();
    long usedMB = (rt.totalMemory() - rt.freeMemory()) / 1024 / 1024;
    logger.information(this, "memory usage" + usedMB);

Ce code fonctionne bien. Cela signifie qu'il montre la courbe de mémoire qui correspond à la réalité. Lorsque nous créons un gros fichier XML à partir d'une base de données, une courbe monte, une fois l'extraction terminée, elle descend.

le texte d'alt

Un consultant nous a dit qu'appeler gc() explicitement est faux, "laissez jvm décider quand exécuter gc". Fondamentalement ses arguments étaient les mêmes comme disscussed ici. Mais je ne comprends toujours pas:

  • comment puis-je avoir ma courbe d'utilisation de la mémoire?
  • quel est le problème avec le gc explicite()? Je ne me soucie pas des petits problèmes de performances qui peuvent se produire avec explicit gc() et que j'estimerais dans 1-3%. Ce dont j'ai besoin, c'est d'un moniteur de mémoire et de thread qui m'aide dans l'analyse de notre système sur le site client.
Author: Community, 2009-06-29

14 answers

Si vous voulez vraiment regarder ce qui se passe dans la mémoire virtuelle, vous devez utiliser un bon outil comme VisualVM. Ce logiciel est gratuit et c'est un excellent moyen de voir ce qui se passe.

Rien n'est vraiment "faux" avec les appels gc() explicites. Cependant, rappelez-vous que lorsque vous appelez gc (), vous "suggérez" que le garbage collector s'exécute. Il n'y a aucune garantie qu'il s'exécutera au moment exact où vous exécutez cette commande.

 48
Author: amischiefr, 2018-01-20 03:29:04

Il existe des outils qui vous permettent de surveiller l'utilisation de la mémoire de la machine virtuelle. La machine virtuelle peut exposer des statistiques de mémoire en utilisant JMX. Vous pouvez également imprimer des statistiques GC pour voir comment la mémoire fonctionne au fil du temps.

Système d'appel.gc () peut nuire aux performances du GC car les objets seront prématurément déplacés de la nouvelle vers l'ancienne génération et les références faibles seront effacées prématurément. Cela peut entraîner une diminution de l'efficacité de la mémoire, des temps de GC plus longs et une diminution des accès au cache (pour les caches qui utilisent des références faibles). Je suis d'accord avec votre consultant: Système.gc() est mauvais. J'irais jusqu'à désactiver en utilisant le commutateur de ligne de commande.

 28
Author: Mr. Shiny and New 安宇, 2016-02-16 16:27:47

Je dirais que le consultant a raison dans la théorie, et vous avez raison dans la pratique. Comme le dit le proverbe :

, En théorie, la théorie et la pratique sont les mêmes. Dans la pratique, ils ne le sont pas.

La spécification Java dit que le système.gc suggère d'appeler la collecte des ordures. En pratique, il génère simplement un thread et s'exécute immédiatement sur la JVM Sun.

Bien qu'en théorie, vous pourriez gâcher une implémentation JVM finement réglée de garbage collection, à moins que vous écrivez du code générique destiné à être déployé sur n'importe quelle JVM, ne vous inquiétez pas à ce sujet. Si cela fonctionne pour vous, faire.

 9
Author: Yishai, 2009-06-29 15:47:58

Vous pouvez jeter un oeil à stagemonitor. Il s'agit d'un moniteur de performance d'application java (web) open source. Il capture les métriques de temps de réponse, les métriques JVM, les détails des demandes (y compris une pile d'appels capturée par le profileur de demandes) et plus encore. Les frais généraux sont très bas.

En option, vous pouvez utiliser la grande base de données timeseries graphite avec elle pour stocker une longue histoire de points de données que vous pouvez regarder avec des tableaux de bord de fantaisie.

Exemple: Tableau de Bord de la mémoire JVM

Jetez un oeil à la site web du projet pour voir des captures d'écran, des descriptions de fonctionnalités et de la documentation.

Remarque: je suis le développeur de stagemonitor

 9
Author: Felix, 2014-07-30 15:01:50

Jetez un coup d'œil à ce qui se passe à l'intérieur de tomcat via Visual VM. http://www.skill-guru.com/blog/2010/10/05/increasing-permgen-size-in-your-server / le texte d'alt

le texte d'alt

 6
Author: vsingh, 2010-10-06 21:27:10

Jetez un oeil aux arguments de la JVM: http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp#DebuggingOptions

XX:-PrintGC Imprimer des messages à la collecte des ordures. Gérable.

-XX:-PrintGCDetails Imprimer plus de détails à garbage collection. Gérable. (Introduit dans 1.4.0.)

-XX:-PrintGCTimeStamps Imprimer les horodatages à la récupération de place. Gérable (Introduit dans 1.4.0.)

-XX:-PrintTenuringDistribution d'Impression tenuring l'âge de l'information.

Bien que vous n'alliez pas perturber la JVM avec des appels explicites à System.gc(), ils peuvent ne pas avoir l'effet que vous attendez. Pour vraiment comprendre ce qui se passe avec la mémoire dans une JVM avec lire tout et n'importe quoi le Brian Goetz écrit.

 5
Author: Nick Holt, 2009-06-29 16:03:39

Exécutant explicitement le système.gc() sur un système de production est une idée terrible. Si la mémoire atteint n'importe quelle taille, le système entier peut geler pendant qu'un GC complet est en cours d'exécution. Sur un serveur de plusieurs gigaoctets, cela peut facilement être très perceptible, selon la façon dont la jvm est configurée, et la marge de manœuvre dont elle dispose, etc etc-j'ai vu des pauses de plus de 30 secondes.

Un autre problème est qu'en appelant explicitement GC, vous ne surveillez pas réellement la façon dont la JVM exécute le GC, vous êtes en fait, en le modifiant-selon la façon dont vous avez configuré la JVM, il va récupérer les ordures le cas échéant, et généralement de manière incrémentielle (il n'exécute pas simplement un GC complet lorsqu'il manque de mémoire). Ce que vous imprimerez ne ressemblera en rien à ce que la JVM fera seule - d'une part, vous verrez probablement moins de GC automatiques / incrémentiels car vous effacerez la mémoire manuellement.

Comme le souligne le post de Nick Holt, les options pour imprimer l'activité GC existent déjà en tant que JVM drapeau.

Vous pourriez avoir un thread qui imprime simplement gratuitement et disponible à des intervalles raisonnables, cela vous montrera l'utilisation réelle de mem.

 5
Author: Steve B., 2009-06-29 16:10:17

Si vous aimez une belle façon de le faire à partir de la ligne de commande utilisez jstat:

Http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jstat.html

Il donne des informations brutes à des intervalles configurables, ce qui est très utile à des fins de journalisation et de représentation graphique.

 4
Author: Pablojim, 2009-06-29 20:01:25

Si vous utilisez java 1.5, vous pouvez regarder ManagementFactory.getMemoryMXBean () qui vous donne chiffres sur toutes sortes de mémoire. tas et non-tas, perm gen.

Un bon exemple peut être trouvé ici http://www.freshblurbs.com/explaining-java-lang-outofmemoryerror-permgen-space

 2
Author: Zoukaye, 2009-06-29 15:57:29

Si vous utilisez l'historique fourni par JMX des exécutions de GC, vous pouvez utiliser les mêmes nombres avant/après, vous n'avez juste pas à forcer un GC.

Vous devez juste garder à l'esprit que ces exécutions GC (généralement une pour l'ancienne et une pour la nouvelle génération) ne sont pas sur des intervalles réguliers, vous devez donc extraire l'heure de début pour le traçage (ou vous tracez contre un numéro de séquence, à des fins plus pratiques qui suffiraient pour le traçage).

Par exemple sur une machine virtuelle Oracle HotSpot avec ParNewGC, il y a un MBean JMX appelé java.lang:type=GarbageCollector,name=PS Scavenge, il a un attribut LastGCInfo, il renvoie un CompositeData de la dernière exécution de YG scavenger. Il est enregistré avec duration, absolu startTime et memoryUsageBefore et memoryUsageAfter.

Utilisez simplement une minuterie pour lire cet attribut. Chaque fois qu'une nouvelle heure de démarrage apparaît, vous savez qu'elle décrit un nouvel événement GC, vous extrayez les informations de mémoire et continuez à interroger pour la prochaine mise à jour. (Je ne sais pas si un AttributeChangeNotification peut en quelque sorte être utilisé.)

Astuce: dans votre minuterie vous pouvez mesurer la distance à la dernière exécution du GC, et si cela est trop long pour la résultante de votre traçage, vous pouvez appeler System.gc () conditionnellement. Mais je ne ferais pas cela dans une instance OLTP.

 2
Author: eckes, 2012-08-15 19:14:53

Comme cela a été suggéré, essayez VisualVM pour obtenir une vue de base.

Vous pouvez également utiliser Eclipse MAT, pour faire une analyse de mémoire plus détaillée.

C'est ok pour faire un système.gc () tant que vous n'en dépendez pas, pour l'exactitude de votre programme.

 0
Author: Aakash, 2009-06-29 19:14:54

Le problème avec le système.gc, c'est que la JVM alloue déjà automatiquement du temps au garbage collector en fonction de l'utilisation de la mémoire.

Cependant, si vous travaillez, par exemple, dans un état très limité en mémoire, comme un appareil mobile, le système.gc vous permet d'allouer manuellement plus de temps à cette récupération de place, mais au prix du temps cpu (mais, comme vous l'avez dit, vous n'êtes pas si préoccupé par les problèmes de performance de gc).

La Meilleure pratique probablement être à utilisez-le uniquement là où vous pourriez faire de grandes quantités de désallocation (comme vider un grand tableau).

Tout considéré, puisque vous êtes simplement préoccupé par l'utilisation de la mémoire, n'hésitez pas à appeler gc, ou, mieux encore, voir si cela fait une grande différence de mémoire dans votre cas, puis décider.

 0
Author: bgw, 2009-06-29 22:04:03

Ajout à la liste des réponses, JConsole (inclus dans le répertoire jdk/bin) est également une bonne interface à essayer.

Référence

 0
Author: Ankit, 2017-04-11 14:01:53