Outil en ligne de commande pour trouver la taille du tas Java et la mémoire utilisée (Linux)?


171

Existe-t-il un outil de ligne de commande (Linux) pour vérifier la taille du tas (et la mémoire utilisée) d'une application Java?

J'ai essayé via jmap. Mais cela donne des informations. sur les zones de mémoire interne comme Eden / PermGen etc., ce qui ne m'est pas utile.

Je recherche quelque chose comme:

  • Mémoire maximale: 1 Go
  • Mémoire minimale: 256 Mo
  • Mémoire de tas: 700 Mo
  • Mémoire utilisée: 460 Mo

C'est tout. Je sais que je peux voir cela dans JConsole etc., mais j'ai besoin d'un outil de ligne de commande (impossible d'activer JMX etc.)

Connaissez-vous un tel outil / commande?

Réponses:


150

Chaque processus Java a un pid, que vous devez d'abord trouver avec la jpscommande.

Une fois que vous avez le pid, vous pouvez l'utiliser jstat -gc [insert-pid-here]pour trouver des statistiques sur le comportement du tas récupéré.

  • jstat -gccapacity [insert-pid-here] présentera des informations sur la génération du pool de mémoire et les capacités d'espace.

  • jstat -gcutil [insert-pid-here]présentera l'utilisation de chaque génération en pourcentage de sa capacité. Utile pour avoir une vue d'ensemble de l'utilisation.

Voir la documentation jstat sur le site d'Oracle.


11
Existe-t-il une recommandation jstatparmi les options à utiliser pour vérifier uniquement l'utilisation globale de la mémoire d'une JVM? Disons que vous démarrez la JVM avec Xms=4get Xmx=4get que vous voulez voir, quelle quantité de mémoire est déjà utilisée?
basZero

1
"jstat -gcutil <pid> 250 N" était très utile pour prélever N échantillons avec des intervalles de 250 ms et afficher la sortie sous forme de pourcentages pour les espaces correspondants. Merci.
Kerem

3
A noter citation de jstatmanuel Oracle Java 8 Page : This command is experimental and unsupported.
patryk.beza

1
awk 'print {$3+$4+$6+$8}'peut imprimer l'utilisation résumée sur les colonnes jstat de Java 8
cybersoft

J'ai eu des problèmes avec les autres réponses, mais une base ps -ef | grep javam'a montré les arguments vm, qui dans mon cas incluaient la valeur -Xmx, qui était tout ce dont j'avais besoin.
xdhmoore

66

jvmtop est un outil de ligne de commande qui fournit une vue en direct à plusieurs métriques, y compris le tas.

Exemple de sortie du mode de vue d'ensemble VM:

 JvmTop 0.3 alpha (expect bugs)  amd64  8 cpus, Linux 2.6.32-27, load avg 0.12
 http://code.google.com/p/jvmtop

  PID MAIN-CLASS      HPCUR HPMAX NHCUR NHMAX    CPU     GC    VM USERNAME   #T DL
 3370 rapperSimpleApp  165m  455m  109m  176m  0.12%  0.00% S6U37 web        21
11272 ver.resin.Resin [ERROR: Could not attach to VM]
27338 WatchdogManager   11m   28m   23m  130m  0.00%  0.00% S6U37 web        31
19187 m.jvmtop.JvmTop   20m 3544m   13m  130m  0.93%  0.47% S6U37 web        20
16733 artup.Bootstrap  159m  455m  166m  304m  0.12%  0.00% S6U37 web        46

C'est en effet un excellent outil, une sorte de htop mais avec des métriques de jstat. Merci pour la suggestion, @MRalwasser.
oski86

65

Cette commande affiche les tailles de tas configurées en octets.

java -XX:+PrintFlagsFinal -version | grep HeapSize

Cela fonctionne également sur Amazon AMI sur EC2.


27
Cela ne répond pas à la question, qui demande spécifiquement comment vérifier l'utilisation du tas d'un processus. La commande ici répertorie les valeurs par défaut de JVM pour tous les processus.
Madbreaks

10
Pourtant, c'est une réponse très utile pour moi de venir sur cette page via une recherche Google sur la façon de trouver la taille globale du tas.
Johan

@jumping_monkey non indirect, incorrect. Si ce que vous dites est vrai, la réponse doit être modifiée ou vous devriez vous sentir libre d'ajouter une nouvelle réponse.
Madbreaks

43

Essayez ceci, cela a fonctionné dans Ubuntu et RedHat:

java -XX:+PrintFlagsFinal -version | grep -iE 'HeapSize|PermSize|ThreadStackSize'

Pour les fenêtres:

java -XX:+PrintFlagsFinal -version | findstr /i "HeapSize PermSize ThreadStackSize"

Pour Mac

java -XX:+PrintFlagsFinal -version | grep -iE 'heapsize|permsize|threadstacksize'

La sortie de toutes ces commandes ressemble à la sortie ci-dessous:

uintx InitialHeapSize                          := 20655360        {product}
uintx MaxHeapSize                              := 331350016       {product}
uintx PermSize                                  = 21757952        {pd product}
uintx MaxPermSize                               = 85983232        {pd product}
intx ThreadStackSize                           = 1024            {pd product}
java version "1.7.0_05"
Java(TM) SE Runtime Environment (build 1.7.0_05-b05)
Java HotSpot(TM) 64-Bit Server VM (build 23.1-b03, mixed mode)

Pour trouver la taille en Mo, divisez la valeur par (1024 * 1024).


Comment trouver l'utilisation de la mémoire séparée par tas, permsize, ... d'un processus java spécifique par pid?
Gary Gauh

3
@GaryGauh Il s'agit de la taille de tas par défaut. Pour trouver l'utilisation de l'application en cours d'exécution, vous devez le faire dans le code ou vous pouvez utiliser jconsole. C'est ce que je sais qu'il devrait y avoir de nombreuses autres façons.
padippist

2
Utilisez jstat -gc <vmid>pour exécuter des applications.
Micha Wiedenmann

28

Sans utiliser JMX, ce que la plupart des outils utilisent, tout ce que vous pouvez faire est d'utiliser

jps -lvm

et déduire que les paramètres proviendront des options de ligne de commande.

Vous ne pouvez pas obtenir d'informations dynamiques sans JMX par défaut, mais vous pouvez écrire votre propre service pour ce faire.

BTW: Je préfère utiliser VisualVM plutôt que JConsole.


25

Il existe un outil de ligne de commande avec un aspect visuel - jvm-mon . Il s'agit d'un outil de surveillance JVM pour la ligne de commande qui affiche:

  • utilisation, taille et maximum du tas
  • processus jvm
  • utilisation du processeur et du GC
  • fils supérieurs

Les métriques et les graphiques sont mis à jour lorsque l'outil est ouvert.

Échantillon: jvm-mon


1
Juste pour noter que jvm-mon ne fonctionne que pour Java8
tmanolatos

1
^ Il existe une nouvelle version qui prend désormais également en charge Java 11.
Andrejs

11

Tard à la fête, mais une solution très simple consiste à utiliser le script jpsstat.sh. Il fournit un moyen simple en direct la mémoire actuelle , mémoire max et utilisation cpu détails.

  • Aller projet GitHub et télécharger le jpsstat.sh fichier
  • Faites un clic droit sur jpsstat.sh et accédez aux autorisations onglet et rendez-le exécutable
  • Exécutez maintenant le script à l'aide de la commande suivante ./jpsstat.sh

Voici l'exemple de sortie du script -

=====  ======  =======  =======  =====
 PID    Name   CurHeap  MaxHeap  %_CPU
=====  ======  =======  =======  =====
2777   Test3      1.26     1.26    5.8
2582   Test1      2.52     2.52    8.3
2562   Test2      2.52     2.52    6.4

ne semble pas fonctionner directement sur un SUSE Linux (ligne 38: déclarer: -A: option invalide)
Chris

on dirait que vous obtenez une erreur dans la déclaration de tableau associatif qui nécessite bash> = 4. Un autre problème peut également être dû à l'exécution du script en tant que "sh jpsstat.sh". Si tel est le cas, essayez d'exécuter le script en tant que "./jpsstat.sh".
amarjeetAnand

9

Dans mon cas, j'avais besoin de vérifier les drapeaux à l'intérieur d'un conteneur de docker qui n'avait pas la plupart des utilitaires de base (ps, pstree ...)

En utilisant, jpsj'ai obtenu le PID de la JVM en cours d'exécution (dans mon cas 1), puis avec jcmd 1 VM.flagsles indicateurs de la JVM en cours d'exécution.

Cela dépend des commandes dont vous disposez, mais cela peut aider quelqu'un. :)


8

À partir de Java8 et supérieur , vous pouvez utiliser la commande ci-dessous:

jcmd JAVA_PROCESS_IDGC.heap_info

Vous pouvez faire référence à la somme, à la mémoire totale et utilisée à partir de la sortie.

Sample Command And Output: jcmd 9758 GC.heap_info

PSYoungGen  total 1579520K, used 487543K [0x0000000751d80000, 0x00000007c0000000, 0x00000007c0000000)
  eden space 1354240K, 36% used [0x0000000751d80000,0x000000076f99dc40,0x00000007a4800000)
  from space 225280K, 0% used [0x00000007b2400000,0x00000007b2400000,0x00000007c0000000)
  to   space 225280K, 0% used [0x00000007a4800000,0x00000007a4800000,0x00000007b2400000)
ParOldGen       total 3610112K, used 0K [0x0000000675800000, 0x0000000751d80000, 0x0000000751d80000)
  object space 3610112K, 0% used [0x0000000675800000,0x0000000675800000,0x0000000751d80000)
Metaspace       used 16292K, capacity 16582K, committed 16896K, reserved 1064960K
  class space    used 1823K, capacity 1936K, committed 2048K, reserved 1048576K

Pour plus de détails sur la commande jcmd, visitez le lien: https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr006.html


1
Vous devez corriger votre commentaire. GC.heap_info est disponible dans Java 9 et supérieur. Il n'est pas disponible dans Java 8. Voir un autre fil de discussion ici: stackoverflow.com/questions/41891127/…
Pavel Molchanov

@PavelMolchanov Je peux utiliser la commande dans jdk1.8.0_172. /Library/Java/JavaVirtualMachines/jdk1.8.0_172.jdk/Contents/Home/bin/jcmd 98270 GC.heap_info. S'il vous plaît, si vous le pouvez, ajoutez les informations au fil de discussion référé ainsi que je n'ai pas assez de réputation pour le moment pour ajouter un commentaire là-bas.
vaibhav gupta

Utilisez-vous Mac? Utilisez-vous Oracle JDK? Je ne sais pas comment cela peut être disponible dans votre jdk1.8.0_172, Oracle a documenté cette fonctionnalité uniquement dans Java 9 et plus: docs.oracle.com/javase/9/tools/jcmd.htm . Ce n'est pas dans la documentation Oracle JDK pour Java 8. Ce n'est pas mentionné dans le lien que vous avez donné en bas: docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/…
Pavel Molchanov

Encore une question. Veuillez vérifier la version JDK qui exécute le processus 98270 dans votre exemple. jcmd obtient les commandes disponibles de la JVM du processus (dans votre cas 98270). Si le processus 98270 est exécuté avec un JDK différent (JDK 9 ou supérieur), vous verrez que la commande GC.heap_info disponible même dans JCMD lui-même provient de Java 8. Les commandes disponibles peuvent être différentes pour différents processus. Pour obtenir les commandes disponibles, exécutez: jcmp <PID> help.
Pavel Molchanov

1
FWIW, GC.heap_infoest définitivement disponible dans OpenJDK 8 également. Peut-être seulement dans les versions récentes? J'utilise celui-ci: 8u191-b12-2ubuntu0.18.04.1
Per Lundberg

7

Toute approche devrait vous donner à peu près le même nombre. C'est toujours une bonne idée d'allouer le tas en utilisant -X..m -X..xpour toutes les générations. Vous pouvez alors garantir et également faire ps pour voir quels paramètres ont été passés et donc utilisés.

Pour les utilisations réelles de la mémoire, vous pouvez comparer approximativement VIRT (alloué et partagé) et RES (réellement utilisé) aux valeurs jstat:

Pour Java 8, voir jstat pour ces valeurs signifient réellement. En supposant que vous exécutiez une classe simple sans mmap ni traitement de fichier.

$ jstat -gccapacity 32277
 NGCMN    NGCMX     NGC     S0C   S1C       EC      OGCMN      OGCMX       OGC         OC       MCMN     MCMX      MC     CCSMN    CCSMX     CCSC    YGC    FGC
215040.0 3433472.0  73728.0  512.0  512.0  67072.0   430080.0  6867968.0   392704.0   392704.0      0.0 1083392.0  39680.0      0.0 1048576.0   4864.0   7225     2
$ jstat -gcutil 32277
  S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT
  6.25   0.00   7.96  18.21  98.01  95.29   7228   30.859     2    0.173   31.032

Max :

     NGCMX + S0C + S1C + EC    + OGCMX   + MCMX    + CCSMX
   3433472 + 512 + 512 + 67072 + 6867968 + 1083392 + 1048576 = 12 GB

(à peu près proche et inférieur à la mémoire VIRT)

Max (Min, utilisé):

215040 + 512 + 512 + 67072 + 430080  + 39680    +  4864  = ~ 1GB

(à peu près proche de la mémoire RES)

"Ne me citez pas là-dessus" mais VIRT mem est à peu près proche ou supérieur à la mémoire maximale allouée, mais tant que la mémoire utilisée est libre / disponible dans la mémoire physique, JVM ne lance pas d'exception de mémoire. En fait, la mémoire maximale n'est même pas vérifiée par rapport à la mémoire physique au démarrage de la JVM, même avec la permutation sur le système d'exploitation. Une meilleure explication de la mémoire virtuelle réellement utilisée par un processus Java est présentée ici .


4

Commencez par obtenir l'identifiant du processus, le premier numéro du processus répertorié, à partir de l'un des éléments suivants: (ou utilisez simplement ps aux | grep java, si vous préférez cela)

jps -lvm

Utilisez ensuite l'ID de processus ici:

jmap -heap $MY_PID 2>/dev/null | sed -ne '/Heap Configuration/,$p';
jmap -permstat $MY_PID

2

L'utilisation de la topcommande est le moyen le plus simple de vérifier l'utilisation de la mémoire du programme. RESLa colonne montre la mémoire physique réelle occupée par un processus.

Pour mon cas, j'avais un fichier 10g lu en java et chaque fois que je sortais d'exception outOfMemory. Cela se produit lorsque la valeur de la REScolonne atteint la valeur définie dans -Xmxoption. Ensuite, en augmentant la mémoire en utilisant l' -Xmxoption, tout s'est bien passé.


3
La commande top indique la quantité de système d'exploitation donnée à la JVM. ce gars demande comment nous pouvons voir l'utilisation de l'espace de tas dans JVM. JVM utilise 10g ne signifie pas que l'espace réel du tas est plein de données 10g, car jvm ne renvoie presque jamais la mémoire au système d'exploitation à partir du tas jusqu'à ce que vous arrêtiez le processus.
linehrr

2

En termes de taille de tas Java, sous Linux, vous pouvez utiliser

ps aux | grep java

ou

ps -ef | grep java

et recherchez -Xms, -Xmx pour connaître la taille de tas initiale et maximale spécifiée.

Cependant, si -Xms ou -Xmx est absent pour le processus Java qui vous intéresse, cela signifie que votre processus Java utilise les tailles de tas par défaut. Vous pouvez utiliser la commande suivante pour connaître les tailles par défaut.

java -XX:+PrintFlagsFinal -version | grep HeapSize

ou une jvm particulière, par exemple,

/path/to/jdk1.8.0_102/bin/java -XX:+PrintFlagsFinal -version | grep HeapSize

et recherchez InitialHeapSize et MaxHeapSize, qui sont en octets.


1

Si vous utilisez jrockit, essayez l'outil de ligne de commande jrcmd. Par exemple:

$ jrcmd 5127 print_memusage
5127:
Total mapped                  1074596KB           (reserved=3728KB)
-              Java heap       786432KB           (reserved=0KB)
-              GC tables        26316KB          
-          Thread stacks        13452KB           (#threads=34)
-          Compiled code         9856KB           (used=9761KB)
-               Internal          840KB          
-                     OS        15036KB          
-                  Other       146632KB          
-        Java class data        75008KB           (malloced=74861KB #103221 in 18709 classes)
- Native memory tracking         1024KB           (malloced=102KB #8)

Pour plus de commandes, comme heap_diagnostics, utilisez "jrcmd help" pour les lister.

https://blogs.oracle.com/jrockit/entry/why_is_my_jvm_process_larger_t


1
jstat -gccapacity javapid  (ex. stat -gccapacity 28745)
jstat -gccapacity javapid gaps frames (ex.  stat -gccapacity 28745 550 10 )

Exemple d'O / P de la commande ci-dessus

NGCMN    NGCMX     NGC     S0C  
87040.0 1397760.0 1327616.0 107520.0 

NGCMN   Minimum new generation capacity (KB).
NGCMX   Maximum new generation capacity (KB).
NGC Current new generation capacity (KB).

Obtenez plus de détails à ce sujet sur http://docs.oracle.com/javase/1.5.0/docs/tooldocs/share/jstat.html


1

Il n'y a pas d'outil de ce type jusqu'à présent pour imprimer la mémoire du tas dans le format que vous avez demandé Le seul et unique moyen d'imprimer est d'écrire un programme java à l'aide de Runtime Class ,

public class TestMemory {

public static void main(String [] args) {

    int MB = 1024*1024;

    //Getting the runtime reference from system
    Runtime runtime = Runtime.getRuntime();

    //Print used memory
    System.out.println("Used Memory:" 
        + (runtime.totalMemory() - runtime.freeMemory()) / MB);

    //Print free memory
    System.out.println("Free Memory:" 
        + runtime.freeMemory() / mb);

    //Print total available memory
    System.out.println("Total Memory:" + runtime.totalMemory() / MB);

    //Print Maximum available memory
    System.out.println("Max Memory:" + runtime.maxMemory() / MB);
}

}

référence: https://viralpatel.net/blogs/getting-jvm-heap-size-used-memory-total-memory-using-java-runtime/


c'est faux. jmap -heap <pid> donne cette info
vsingh

0

Trouvez l'ID de processus de votre processus webapp / java en haut. Utilisez le tas jmap pour obtenir l'allocation du tas. J'ai testé cela sur AWS-Ec2 pour le haricot élastique

Vous pouvez voir dans l'image ci-dessous 3 Go de tas maximum pour l'application

entrez la description de l'image ici

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.