Jmap ne peut pas se connecter pour créer un vidage

Nous avons une version bêta ouverte d’une application qui provoque parfois un débordement de l’espace disque. La JVM réagit en partant en vacances permanentes.

Pour parsingr cela, je voudrais jeter un coup d’oeil dans la mémoire au point où il a échoué. Java ne veut pas que je fasse ça. Le processus est toujours en mémoire mais il ne semble pas être reconnu comme un processus Java.

Le serveur en question est un serveur Debian Lenny, Java 6u14

/opt/jdk/bin# ./jmap -F -dump:format=b,file=/tmp/apidump.hprof 11175 Attaching to process ID 11175, please wait... sun.jvm.hotspot.debugger.NoSuchSymbolException: Could not find symbol "gHotSpotVMTypeEntryTypeNameOffset" in any of the known library names (libjvm.so, libjvm_g.so, gamma_g) at sun.jvm.hotspot.HotSpotTypeDataBase.lookupInProcess(HotSpotTypeDataBase.java:390) at sun.jvm.hotspot.HotSpotTypeDataBase.getLongValueFromProcess(HotSpotTypeDataBase.java:371) at sun.jvm.hotspot.HotSpotTypeDataBase.readVMTypes(HotSpotTypeDataBase.java:102) at sun.jvm.hotspot.HotSpotTypeDataBase.(HotSpotTypeDataBase.java:85) at sun.jvm.hotspot.bugspot.BugSpotAgent.setupVM(BugSpotAgent.java:568) at sun.jvm.hotspot.bugspot.BugSpotAgent.go(BugSpotAgent.java:494) at sun.jvm.hotspot.bugspot.BugSpotAgent.attach(BugSpotAgent.java:332) at sun.jvm.hotspot.tools.Tool.start(Tool.java:163) at sun.jvm.hotspot.tools.HeapDumper.main(HeapDumper.java:77) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at sun.tools.jmap.JMap.runTool(JMap.java:179) at sun.tools.jmap.JMap.main(JMap.java:110) Debugger attached successfully. sun.jvm.hotspot.tools.HeapDumper requires a java VM process/core! 

La solution était très simple. J’exécutais jmap en tant que root, mais je devais l’exécuter en tant qu’utilisateur ayant démarré le jvm. Je vais maintenant aller cacher ma tête dans la honte.

J’exécutais jmap et l’application avec le même utilisateur et j’obtiens toujours l’erreur.

La solution a été lancée avant le jmap

 echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope 

C’est juste utiliser jmap et ça va bien

 jmap -heap 17210 

Futurs Googlers:

Cela pourrait également arriver si vous avez installé le JDK pendant que le processus que vous essayez de faire avec jmap était en cours d’exécution.

Si tel est le cas, redémarrez le processus java.

Si quelqu’un essaie d’obtenir Hump Dump de l’application Java dans le conteneur Docker. C’est la seule solution qui a fonctionné pour moi:

 docker exec  jcmd 1 GC.heap_dump /tmp/docker.hprof 

Il vide essentiellement le tas de processus avec pid = 1 en utilisant jcmd

Voir https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr006.html

Qu’est-ce qui se passe si vous venez de courir

 ./jmap -heap 11175 

Et êtes-vous sûr que l’application JVM est identique à la JVM JMAP? (même version, etc.)

J’ai eu la même erreur jmap sur une machine Linux qui a deux OpenJdks différents installés. J’ai d’abord installé OpenJDK 1.6 et après cela OpenJDK 1.7.

Un appel de …

 /usr/lib/jvm/java-1.7.0-openjdk-amd64/bin/java -XshowSettings:properties -version # produce the following output ... ... java.library.path = /usr/java/packages/lib/amd64 /usr/lib/x86_64-linux-gnu/jni /lib/x86_64-linux-gnu /usr/lib/x86_64-linux-gnu /usr/lib/jni /lib /usr/lib ... java version "1.7.0_65" 

Avec inclure ‘/ usr / lib’, tous les programmes démarrés avec OpenJDK 1.7. * Incluent les bibliothèques du premier JDK installé (dans mon cas, OpenJDK 1.6. *). Les versions jmap de Java6 et Java7 ont donc échoué.

Après avoir modifié le démarrage des programmes Java7 avec les bibliothèques OpenJDK 1.7 incluses …

 /usr/lib/jvm/java-1.7.0-openjdk-amd64/bin/java -Djava.library.path=/usr/lib/jvm/java- \ 7-openjdk-amd64/jre/lib/amd64/server:/usr/java/packages/lib/amd64: \ /usr/lib/x86_64-linux-gnu/jni:/lib/x86_64-linux-gnu:/usr/lib/ \ x86_64-linux-gnu:/usr/lib/jni:/lib:/usr/lib ... 

J’ai pu accéder à Proccess avec la version Java 7 du programme jmap. Mais il faut un sudo pour fonctionner.

Vous devez utiliser le jmap fourni avec la JVM.

Ce qui a fonctionné pour moi était de simplement lancer la commande avec sudo comme dans:

 sudo jmap -heap 21797 

Suivez les étapes ci-dessous pour prendre le thread et le vidage de tas depuis un conteneur de docker

  1. Exécutez la commande ci-dessous pour entrer dans le conteneur. Veuillez modifier le CONTAINER_NAME de manière appropriée
  docker exec -it CONTAINER_NAME bash 
  1. Ensuite, tapez jps pour trouver tous les détails de l’application Java et extraire le PID pour votre application
 jps 
  1. Ensuite, exécutez la commande ci-dessous pour obtenir le vidage de fil. Veuillez modifier le PID de manière appropriée

     jstack PID > threadDump.tdump 
  2. Ensuite, exécutez la commande ci-dessous pour obtenir le vidage du tas. Veuillez modifier le PID de manière appropriée

  jmap -dump:live,format=b,file=heapDump.hprof PID 
  1. Quittez ensuite le conteneur docker et téléchargez les threadDump.tdump et heapDump.hprof à partir du conteneur docker en exécutant la commande ci-dessous. Veuillez modifier le CONTAINER_NAME de manière appropriée
  sudo docker cp CONTAINER_NAME:threadDump.tdump . sudo docker cp CONTAINER_NAME:heapDump.hprof . 
 1.Execute "Docker ps", will give the container Id of all services and collect the container id foe TSC. 2.Execute "docker exec -it CONTAINER_ID bash" (replace CONTAINER_ID with TSC Container id) 3.Bash will come and then execute the "jps" on bash, that will give you the PID for process(it will be 1 for jar) 4.Execute the "jstack PID > threadDump.tdump"(replace PID with process id received in step 3, it should be 1) 5.Execute the "jmap -dump:format=b,file=heapDump.hprof PID"(replace PID with process id received in step 3, it should be 1) 6.Then we have to exit the bash using "exit" command 7.Execute "sudo docker cp CONTAINER_ID:heapDump.hprof ." from ec2 command line, that will copy the dump file on ec2 machine present working directory. 8.Execute "sudo docker cp CONTAINER_ID:threadDump.tdump ." from ec2 command line, that will copy the dump file on ec2 machine present working directory. 

J’ai le même problème, j’essaie de trouver une fuite de mémoire dans un processus exécuté dans un conteneur Docker. Je n’ai pas pu utiliser jmap, mais j’ai utilisé ceci:

 jcmd  GC.class_histogram 

Cela vous donne une liste des objects dans la mémoire. Et à partir de la documentation Oracle:

Il est recommandé d’utiliser le dernier utilitaire, jcmd, au lieu de l’utilitaire jmap, pour des diagnostics améliorés et une réduction des performances. https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/memleaks004.html

Si aucun de ces éléments ne fonctionne ou si vous ne souhaitez pas modifier les indicateurs sensibles du système d’exploitation tels que ptrace_scope:

Soit vous pouvez utiliser jconsole / jvisualvm pour déclencher des vidages de tas ou exécuter n’importe quel client JMX directement depuis la console, comme vous le faites localement sur la machine qui a besoin du vidage et donc plus rapidement:

 echo 'jmx_invoke -m com.sun.management:type=HotSpotDiagnostic dumpHeap heapdump-20160309.hprof false' | java -jar jmxsh.jar -h $LOCALHOST_OR_IP -p $JMX_PORT 

J’ai utilisé le https://github.com/davr/jmxsh/raw/master/jmxsh.jar wget pour cet exemple.

Dans mon cas, ce n’est pas aussi simple que de vérifier l’utilisateur 🙁

J’ai un script appelé collectd-java qui appelle jstat et jmap. J’ai vérifié par le haut que ce script est lancé, comme prévu, par l’utilisateur propriétaire de la JVM. Cependant, jstat me donne ce dont j’ai besoin et jmap ne peut pas joindre. Voici le script: les échos sont juste le format dont j’ai besoin pour présenter les valeurs:

 HOSTNAME="${COLLECTD_HOSTNAME:-localhost}" INTERVAL="${COLLECTD_INTERVAL:-60}" MAIN_CLASS="my.fully.qualified.MainClass" PID=$(pgrep -f ${MAIN_CLASS}) get_jstat_classloaderdata() { VALUE=`jstat -class $PID 1 1 | awk '{print $1}' | grep -vi loaded` echo "PUTVAL \"$HOSTNAME/exec-cecoco/gauge-java_classloader_loaded\" interval=$INTERVAL N:$VALUE" VALUE=`jstat -class $PID 1 1 | awk '{print $2}' | grep -vi bytes` echo "PUTVAL \"$HOSTNAME/exec-cecoco/gauge-java_classloader_bytesload\" interval=$INTERVAL N:$VALUE" VALUE=`jstat -class $PID 1 1 | awk '{print $3}' | grep -vi unload` echo "PUTVAL \"$HOSTNAME/exec-cecoco/gauge-java_classloader_unloaded\" interval=$INTERVAL N:$VALUE" VALUE=`jstat -class $PID 1 1 | awk '{print $4}' | grep -vi bytes` echo "PUTVAL \"$HOSTNAME/exec-cecoco/gauge-java_classloader_bytesunload\" interval=$INTERVAL N:$VALUE" VALUE=`jstat -class $PID 1 1 | awk '{print $5}' | grep -vi time` echo "PUTVAL \"$HOSTNAME/exec-cecoco/gauge-java_classloader_time\" interval=$INTERVAL N:$VALUE" } get_jmap_heapdata() { VALUE=$(jmap -heap ${PID} | grep MinHeapFreeRatio |awk '{print $3}') echo "PUTVAL \"$HOSTNAME/exec-cecoco/gauge-jmap_minheapfreeratio\" interval=$INTERVAL N:$VALUE" VALUE=$(jmap -heap ${PID} | grep MaxHeapFreeRatio|awk '{print $3}') echo "PUTVAL \"$HOSTNAME/exec-cecoco/gauge-jmap_maxheapfreeratio\" interval=$INTERVAL N:$VALUE" VALUE=$(jmap -heap ${PID} | grep MaxHeapSize|awk '{print $3}') echo "PUTVAL \"$HOSTNAME/exec-cecoco/gauge-jmap_maxheapsize\" interval=$INTERVAL N:$VALUE" } ##Do it get_jmap_heapdata get_jstat_classloaderdata 

Jstat réussit et jmap échoue. Est-ce que quelqu’un le comprend?

Je ne sais pas pourquoi un simple “jmap” échoue lorsque je docker exec -it dans mon conteneur exécutant centos7 systemd et un service java, mais les options jmap ci-dessous ont fonctionné pour moi. Merci: https://dkbalachandar.wordpress.com/2016/07/05/thread-dump-from-a-docker-container/

[root@b29924306cfe /]# jmap 170 Attaching to process ID 170, please wait... Error attaching to process: sun.jvm.hotspot.debugger.DebuggerException: Can't attach to the process: ptrace(PTRACE_ATTACH, ..) failed for 170: Operation not permitted sun.jvm.hotspot.debugger.DebuggerException: sun.jvm.hotspot.debugger.DebuggerException: Can't attach to the process: ptrace(PTRACE_ATTACH, ..) failed for 170: Operation not permitted

[root@b29924306cfe /]# jmap -dump:live,format=b,file=heapDump.hprof 170 Dumping heap to /heapDump.hprof ... Heap dump file created