Capture d'un vidage de thread Java

1. Vue d'ensemble

Dans ce didacticiel, nous aborderons différentes manières de capturer le vidage de thread d'une application Java.

Un thread dump est un instantané de l'état de tous les threads d'un processus Java . L'état de chaque thread est présenté avec une trace de pile, montrant le contenu de la pile d'un thread. Un vidage de thread est utile pour diagnostiquer les problèmes car il affiche l'activité du thread. Les threads de vidage sont écrits en texte brut, nous pouvons donc enregistrer leur contenu dans un fichier et les consulter plus tard dans un éditeur de texte .

Dans les sections suivantes, nous passerons en revue plusieurs outils et approches pour générer un thread dump.

2. Utilisation des utilitaires JDK

Le JDK fournit plusieurs utilitaires qui peuvent capturer le vidage de thread d'une application Java. Tous les utilitaires se trouvent sous le dossier bin dans le répertoire de base JDK . Par conséquent, nous pouvons exécuter ces utilitaires à partir de la ligne de commande tant que ce répertoire est dans notre chemin système.

2.1. jstack

jstack est un utilitaire JDK de ligne de commande que nous pouvons utiliser pour capturer un vidage de thread. Il prend le pid d'un processus et affiche le vidage de thread dans la console. Alternativement, nous pouvons rediriger sa sortie vers un fichier.

Jetons un coup d'œil à la syntaxe de commande de base pour capturer un vidage de thread à l'aide de jstack:

jstack [-F] [-l] [-m] 

Tous les drapeaux sont facultatifs. Voyons ce qu'ils signifient:

  • L' option -F force un vidage de thread; pratique à utiliser lorsque jstack pid ne répond pas (le processus est bloqué)
  • L' option -l demande à l'utilitaire de rechercher des synchroniseurs possédables dans le tas et les verrous
  • L'option -m imprime les cadres de pile natifs (C & C ++) en plus des cadres de pile Java

Utilisons ces connaissances en capturant un vidage de thread et en redirigeant le résultat vers un fichier:

jstack 17264 > /tmp/threaddump.txt

N'oubliez pas que nous pouvons facilement obtenir le pid d'un processus Java en utilisant la commande jps .

2.2. Contrôle de mission Java

Java Mission Control (JMC) est un outil GUI qui collecte et analyse les données des applications Java. Après avoir lancé JMC, il affiche la liste des processus Java s'exécutant sur une machine locale. Nous pouvons également nous connecter à des processus Java distants via JMC.

Nous pouvons faire un clic droit sur le processus et cliquer sur l' option « Démarrer l'enregistrement de vol ». Après cela, l' onglet Threads affiche les Thread Dumps:

2.3. jvisualvm

jvisualvm est un outil avec une interface utilisateur graphique qui nous permet de surveiller, dépanner et profiler les applications Java . L'interface graphique est simple mais très intuitive et facile à utiliser.

Une de ses nombreuses options nous permet de capturer un thread dump. Si nous faisons un clic droit sur un processus Java et sélectionnons l' option "Thread Dump" , l'outil créera un thread dump et l'ouvrira dans un nouvel onglet:

À partir du JDK 9, Visual VM n'est pas inclus dans les distributions Oracle JDK et Open JDK. Par conséquent, si nous utilisons Java 9 ou des versions plus récentes, nous pouvons obtenir JVisualVM à partir du site de projet open source Visual VM.

2.4. jcmd

jcmd est un outil qui fonctionne en envoyant des requêtes de commande à la JVM. Bien que puissant, il ne contient aucune fonctionnalité distante - nous devons l'utiliser sur la même machine où le processus Java s'exécute.

L'une de ses nombreuses commandes est Thread.print . Nous pouvons l'utiliser pour obtenir un vidage de thread simplement en spécifiant le pid du processus:

jcmd 17264 Thread.print

2.5. jconsole

jconsole nous permet d'inspecter la trace de pile de chaque thread. Si nous ouvrons jconsole et nous nous connectons à un processus Java en cours d'exécution, nous pouvons accéder à l' onglet Threads et trouver la trace de pile de chaque thread :

2.6. Sommaire

En fait, il existe de nombreuses façons de capturer un vidage de thread à l'aide des utilitaires JDK. Prenons un moment pour réfléchir à chacun et exposer leurs avantages et inconvénients:

  • jstack : fournit le moyen le plus rapide et le plus simple de capturer un thread dump. Cependant, de meilleures alternatives sont disponibles à partir de Java 8
  • jmc : outil de profilage et de diagnostic JDK amélioré. Cela minimise la surcharge de performances qui est généralement un problème avec les outils de profilage
  • jvisualvm : outil de profilage léger et open-source avec une excellente console GUI
  • jcmd : extrêmement puissant et recommandé pour Java 8 et versions ultérieures. Un outil unique qui sert à plusieurs fins - capture de vidage de thread ( jstack ), de vidage de tas ( jmap ), de propriétés système et d'arguments de ligne de commande ( jinfo )
  • jconsole : inspectons les informations de trace de la pile de threads

3. Depuis la ligne de commande

Dans les serveurs d'applications d'entreprise, seul le JRE est installé pour des raisons de sécurité. Ainsi, nous ne pouvons pas utiliser les utilitaires mentionnés ci-dessus car ils font partie de JDK. Cependant, il existe diverses alternatives en ligne de commande qui nous permettent de capturer facilement les threads dumps.

3.1. Commande kill -3 (Linux / Unix)

Le moyen le plus simple de capturer un vidage de thread dans les systèmes de type Unix est d' utiliser la commande kill , que nous pouvons utiliser pour envoyer un signal à un processus en utilisant l' appel système kill () . Dans ce cas d'utilisation, nous lui enverrons le signal -3 .

En utilisant notre même pid des exemples précédents, voyons comment utiliser kill pour capturer un vidage de thread:

kill -3 17264

This way the signal-receiving Java process will print the thread dump on the standard output.

If we run the Java process with the following combination of tuning flags, then it will also redirect the thread dump to the given file:

-XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=~/jvm.log

Now if we send the -3 signal, in addition to the standard output, the dump will be available at ~/jvm.log file.

3.2. Ctrl + Break (Windows)

In Windows operating systems, we can capture a thread dump using the CTRL and Break key combination. To take a thread dump, navigate to the console used to launch the Java application and press CTRL and Break keys together.

It's worth noting that, on some keyboards, the Break key is not available. Therefore, in such cases, a thread dump can be captured using CTRL, SHIFT, and Pause keys together.

Both of these commands print the thread dump to the console.

4. Programmatically Using ThreadMxBean

The last approach we will discuss in the article is using JMX. We'll use ThreadMxBean to capture the thread dump. Let's see it in code:

private static String threadDump(boolean lockedMonitors, boolean lockedSynchronizers) { StringBuffer threadDump = new StringBuffer(System.lineSeparator()); ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); for(ThreadInfo threadInfo : threadMXBean.dumpAllThreads(lockedMonitors, lockedSynchronizers)) { threadDump.append(threadInfo.toString()); } return threadDump.toString(); }

In the above program, we are performing several steps:

  1. At first, an empty StringBuffer is initialized to hold the stack information of each thread.
  2. We then use the ManagementFactory class to get the instance of ThreadMxBean. A ManagementFactory is a factory class for getting managed beans for the Java platform. In addition, a ThreadMxBean is the management interface for the thread system of the JVM.
  3. Setting lockedMonitors and lockedSynchronizers values to true indicates to capture the ownable synchronizers and all locked monitors in the thread dump.

5. Conclusion

In this article, we've shown multiple ways to capture a thread dump.

At first, we discussed various JDK Utilities and then the command-line alternatives. In the last section, we concluded with the programmatic approach using JMX.

Comme toujours, le code source complet de l'exemple est disponible à l'adresse over sur GitHub.