web-dev-qa-db-fra.com

Exécution de jmap impossible Impossible d'ouvrir le fichier de socket

Je devais exécuter jmap afin de prendre le tas de données de mon processus. mais jvm est retourné:

Unable to open socket file: target process not responding or HotSpot VM not loaded
The -F option can be used when the target process is not responding

J'ai donc utilisé le -F:

./jmap -F -dump:format=b,file=heap.bin 10330
Attaching to process ID 10331, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 24.51-b03
Dumping heap to heap.bin ...
  1. Utiliser -F vous convient-il pour prendre heap dump?
  2. J'attends 20 minutes et je n'ai pas encore fini. Des idées pourquoi?
61
rayman

jmap vs jmap -F, ainsi que jstack contre jstack -F utilisent des mécanismes complètement différents pour communiquer avec la machine virtuelle Java cible.

jmap/jstack

Lorsqu'ils sont exécutés sans -F, ces outils utilisent Mécanisme d'attachement dynamique . Cela fonctionne comme suit.

  1. Avant de se connecter au processus Java 1234, jmap crée un fichier .attach_pid1234 dans le répertoire de travail du processus cible ou à /tmp.

  2. Ensuite, jmap envoie SIGQUIT au processus cible. Lorsque la machine virtuelle Java intercepte le signal et trouve .attach_pid1234, elle démarre le thread AttachListener.

  3. AttachListener thread crée le socket de domaine UNIX /tmp/.Java_pid1234 pour écouter les commandes à partir d'outils externes.

  4. Pour des raisons de sécurité, lorsqu'une connexion (à partir de jmap) est acceptée, JVM vérifie que les informations d'identification de l'homologue de socket sont égales à euid et egid du processus JVM. C'est pourquoi jmap ne fonctionnera pas s'il est exécuté par un utilisateur différent (même par un utilisateur root).

  5. jmap se connecte au socket et envoie la commande dumpheap.

  6. Cette commande est lue et exécutée par le thread AttachListener de la machine virtuelle Java. Toutes les sorties sont renvoyées au socket. Étant donné que le vidage de segment de mémoire est effectué directement dans le processus par la machine virtuelle Java, l'opération est très rapide. Cependant, JVM ne peut le faire qu’au niveau de safepoints . Si un point de sécurité ne peut pas être atteint (par exemple, le processus est bloqué, ne répond pas ou si un GC est long), jmap expirera et échouera.

Résumons les avantages et les inconvénients de Dynamic Attach.

Avantages.

  • Le vidage de tas et d'autres opérations sont exécutées en collaboration par JVM à la vitesse maximale.
  • Vous pouvez utiliser n’importe quelle version de jmap ou jstack pour vous connecter à n’importe quelle version de JVM.

Les inconvénients.

  • L'outil doit être exécuté par le même utilisateur (euidegid) que la machine virtuelle Java cible.
  • Peut être utilisé uniquement sur une machine virtuelle Java vivante et saine.
  • Ne fonctionnera pas si la machine virtuelle Java cible est démarrée avec -XX:+DisableAttachMechanism.

jmap -F/jstack -F

Lorsqu'ils sont exécutés avec -F, les outils basculent vers un mode spécial doté de HotSpot Serviceability Agent . Dans ce mode, le processus cible est gelé. les outils lisent sa mémoire via des fonctions de débogage de système d'exploitation, à savoir, ptrace sur Linux.

  1. jmap -F appelle PTRACE_ATTACH sur la machine virtuelle Java cible. Le processus cible est suspendu sans condition en réponse au signal SIGSTOP.

  2. L'outil lit la mémoire de la machine virtuelle Java à l'aide de PTRACE_PEEKDATA. ptrace ne peut lire qu'un mot à la fois, il faut donc trop d'appels pour lire le gros segment du processus cible. C'est très et très lent.

  3. L'outil reconstruit les structures internes de la machine virtuelle Java en fonction de la connaissance de la version de cette machine. Étant donné que les différentes versions de JVM ont une structure de mémoire différente, le mode -F ne fonctionne que si jmap provient du même JDK que le processus Java cible.

  4. L'outil crée lui-même le vidage de segment puis reprend le processus cible.

_/ Avantages.

  • Aucune coopération de la machine virtuelle cible n'est requise. Peut être utilisé même sur un processus bloqué.
  • ptrace fonctionne chaque fois que les privilèges de niveau système sont suffisants. Par exemple. root peut vider les processus de tous les autres utilisateurs.

Les inconvénients.

  • Très lent pour les gros tas.
  • L'outil et le processus cible doivent provenir de la même version de JDK.
  • Le point de sécurité n’est pas garanti lorsque l’outil s’attache en mode forcé. Bien que jmap essaie de gérer tous les cas particuliers, il peut arriver que la machine virtuelle Java cible ne soit pas dans un état cohérent.

Remarque

Il existe un moyen plus rapide de réaliser des vidages de tas en mode forcé. Commencez par créer un coredump avec gcore , puis exécutez jmap sur le fichier core généré. Voir la question connexe .

124
apangin

Je viens de découvrir que jmap (et vraisemblablement jvisualvm lorsqu’il l’utilise pour générer un vidage de tas) impose que l’utilisateur exécutant jmap soit le même utilisateur exécutant le processus qui tente d’être déchargé.

dans mon cas, le JVM que je veux un tas de vidage est en cours d'exécution par l'utilisateur de Linux "jboss". Alors, où Sudo jmap -dump:file.bin <pid> signalait "Impossible d'ouvrir socket:", j'ai pu récupérer mon tas de données en utilisant:

Sudo -u jboss jmap -dump:file.bin <pid>
68
ben_wing

Si votre application s'exécute en tant que service systemd. Vous devez ouvrir le fichier de service sous /usr/lib/systemd/system/ et nommé par votre nom de service. Puis vérifiez si l'attribut privateTmp est vrai.

Si c'est vrai, vous devez le changer en false, puis actualiser le service par commande comme suit: systemctl daemon-reload systemctl restart [servicename] Si vous souhaitez exécuter jmap/jcmd avant le redémarrage, vous pouvez utiliser le script execStop du fichier de service. Il suffit de mettre la commande et d'exécuter systemctl stop [service name]

0
Simple

Tout comme ben_wing said, vous pouvez exécuter avec:

Sudo -u jboss-as jmap -dump:file.bin <pid>

(Dans mon cas, l'utilisateur est jboss-as, mais le vôtre peut être jboss ou un autre.)

Mais cela ne suffisait pas, car il m'a demandé un mot de passe ([Sudo] password for ec2-user:), bien que je puisse exécuter Sudo sans me demander un mot de passe avec d'autres commandes. 

J'ai trouvé la solution ici , et je devais simplement ajouter une autre variable Sudo:

Sudo sudo -u jboss-as jmap -dump:file.bin <pid>

Cela fonctionne aussi avec d'autres commandes comme jcmd et jinfo.

0