web-dev-qa-db-fra.com

Jmap ne peut pas se connecter pour faire un dump

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

Pour analyser cela, j'aimerais jeter un coup d'œil dans la mémoire au point où cela a échoué. Java ne veut pas que je fasse cela. 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.<init>(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!
49
Jasper Floor

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

79
Jasper Floor

J'exécutais le jmap et l'application avec le même utilisateur et reçois toujours l'erreur.

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

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

Than n’utilise que jmap et fonctionne correctement

jmap -heap 17210
28
jpozorio

Futurs Googlers:

Cela pourrait également se produire si vous avez installé le JDK alors que le processus que vous essayez d'exécuter jmap était en cours d'exécution.

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

13
Ariel T

Si quelqu'un essaie de télécharger Heap Dump d'une application Java dans le conteneur Docker, c'est la seule solution qui fonctionne pour moi:

docker exec <container-name> 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

11
Oleksandr

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

./jmap -heap 11175 

Et êtes-vous sûr que la machine virtuelle d'application est identique à la machine virtuelle JMAP? (même version, etc)

6
bwawok

Vous devez utiliser le jmap fourni avec la machine virtuelle Java.

3
ejaenv

Suivez les étapes ci-dessous pour récupérer le thread et le vidage de segments de mémoire d'un conteneur de menu fixe.

  1. Exécutez la commande ci-dessous pour vous connecter au conteneur. Modifiez CONTAINER_NAME de manière appropriée.
   docker exec -it CONTAINER_NAME bash
  1. Puis tapez jps pour trouver tous les détails de l'application Java et extraire le PID de votre application.
jps
  1. Ensuite, exécutez la commande ci-dessous pour obtenir le vidage de thread. 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 de 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 fichiers threadDump.tdump et heapDump.hprof du conteneur Docker en exécutant la commande ci-dessous. Modifiez CONTAINER_NAME de manière appropriée.
 Sudo docker cp CONTAINER_NAME:threadDump.tdump .
 Sudo docker cp CONTAINER_NAME:heapDump.hprof .
2
Arbaz Alam

J'ai la même erreur jmap sur une machine Linux sur laquelle deux OpenJdks différents sont installés. J'ai d'abord installé OpenJDK 1.6 et ensuite 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 l’inclusion de '/ usr/lib' dans OpenJDK 1.7, le programme lancé inclut 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ébut 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 au processus avec la version Java 7 du programme jmap. Mais il faut un Sudo pour courir.

2
OkieOth

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, j'ai plutôt utilisé ceci: 

jcmd <pid> GC.class_histogram 

Cela vous donne une liste des objets 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 améliorer les diagnostics et réduire les performances. https://docs.Oracle.com/javase/8/docs/technotes/guides/troubleshoot/memleaks004.html

2
Javier Lopez
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.
2
ABHAY JOHRI

Ce qui a fonctionné pour moi a été simplement d’émettre la commande avec Sudo comme dans

Sudo jmap -heap 21797
2
Pablo

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 possédant la machine virtuelle Cependant, jstat me donne ce dont j'ai besoin et jmap ne peut pas être attaché. Voici le script - l'écho est 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?

0
Zirikatzaile

Lorsque rien 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 un client JMX directement à partir de la console, comme suit: vous le faites localement sur la machine qui a besoin du vidage et est donc plus rapide:

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 wget https://github.com/davr/jmxsh/raw/master/jmxsh.jar pour cet exemple.

0
kisna

Je ne sais pas pourquoi une "jmap" simple échoue lorsque je docker exec -it dans mon conteneur exécutant centos7 systemd et un service Java, mais les options ci-dessous de jmap 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

0
jamshid