Développons en Java
v 2.40   Copyright (C) 1999-2023 .   
Partie 17 : Les outils de profiling et monitoring 121. VisualVM Imprimer Index Index avec sommaire Télécharger le PDF

 

120. Arthas

 

chapitre    1 2 0

 

Niveau : niveau 4 Supérieur 
Version utilisée : 3.1.7 

 

Il n'est pas envisageable de déboguer une application en production car cela dégraderait les performances voir interromprait l'exécution pour une durée plus ou moins longue.

Généralement, on tente de reproduire la situation dans un autre environnement mais cela est parfois compliqué notamment lorsque les données et l'environnement ne sont pas similaires, les scénarios ou le timing sont différents.

Il est aussi possible d'ajouter des logs pour obtenir des informations mais cela implique de modifier le code et de redéployer le code en production avec tout ce que cela peut engendrer dans le respect du cycle de vie d'une nouvelle version et surtout l'interruption de service lors de redéploiement. Tout cela pour un résultat qui n'est toujours probant du premier coup et peut éventuellement nécessiter plusieurs itérations.

Arthas est un outil de diagnostic Java open source créé par Alibaba, qui propose de nombreuses fonctionnalités qui peuvent aider à identifier de nombreux problèmes dans des applications exécutées dans une JVM sans avoir à la redémarrer. C'est un outil en mode console qui permet de se connecter à une application Java en cours d'exécution.

Le grand intérêt d'Arthas est de permettre d'obtenir de nombreuses informations pour identifier des problèmes dans une application exécutée dans une JVM sans avoir à rejouter du code ni même de redémarrer la JVM. Arthas peut ainsi être utilisable dans un environnement de production puisqu'il peut être utilisé en ligne de commande locale, sans avoir à redémarrer la JVM.

Arthas offre de nombreuses fonctionnalités qui peuvent être très utiles dans de nombreuses situations notamment :

Arthas est utilisable sur les systèmes d'exploitation Linux, Mac et Windows disposant d'un JDK 6 minimum.

Le site officiel d'Arthas est à l'url : https://alibaba.github.io/arthas/index.html

Le projet est sur GitHub : https://github.com/alibaba/arthas

Ce chapitre contient plusieurs sections :

 

120.1. Installation

Arthas peut être utilisé sur tout système qui possède une JVM Java version 6 minimum.

L'installation peut être réalisée de différentes manières selon le système d'exploitation utilisé.

 

120.1.1. L'installation avec le fichier arthas-boot.jar

Le plus simple pour utiliser Arthas est de télécharger le fichier jar auto-exécutable nommé arthas-boot.jar à l'url https://alibaba.github.io/arthas/arthas-boot.jar

Par exemple en utilisant curl

Résultat :
jm@L-X1:/mnt/c/temp/arthas$ curl https://alibaba.github.io/arthas/arthas-boot.jar --output 
arthas-boot.jar

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  108k  100  108k    0     0  38441      0  0:00:02  0:00:02 --:--:-- 38439
jm@L-X1:/mnt/c/temp/arthas$

ou en utilisant wget

Résultat :
jm@L-X1:/mnt/c/temp/arthas$ wget https://alibaba.github.io/arthas/arthas-boot.jar
--2020-03-13 19:48:29--  https://alibaba.github.io/arthas/arthas-boot.jar
Résolution de alibaba.github.io (alibaba.github.io)... 185.199.109.153, 185.199.111.153,
 185.199.110.153, ...
Connexion à alibaba.github.io (alibaba.github.io)|185.199.109.153|:443... connecté.
requête HTTP transmise, en attente de la réponse... 200 OK
Taille : 111090 (108K) [application/java-archive]
Enregistre : «arthas-boot.jar»
 
arthas-boot.jar              100%[================================================>] 108,49K
   333KB/s    in 0,3s
 
2020-03-13 19:48:31 (333 KB/s) - «arthas-boot.jar» enregistré [111090/111090]
 
jm@L-X1:/mnt/c/temp/arthas$

Il faut exécuter le fichier arthas-boot.jar et avoir une JVM en cours d'exécution pour que l'application puisse s'y connecter. Comme c'est la première exécution, l'application Arthas est téléchargée et installée dans le sous-répertoire .arthas du répertoire home de l'utilisateur.

Résultat :
C:\java> java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.1.7
[INFO] Found existing java process, please choose one and hit RETURN.
* [1]: 4192 arthas-demo.jar
 
[INFO] Start download arthas from remote server: https://repo1.maven.org/maven2/com/taobao/arth
as/arthas-packaging/3.1.7/arthas-packaging-3.1.7-bin.zip
[INFO] File size: 10,33 MB, downloaded size: 108,13 KB, downloading ...
[INFO] File size: 10,33 MB, downloaded size: 270,50 KB, downloading ...
...
[INFO] File size: 10,33 MB, downloaded size: 10,17 MB, downloading ...
[INFO] File size: 10,33 MB, downloaded size: 10,33 MB, downloading ...
[INFO] Download arthas success.
[INFO] arthas home: C:\Users\jm\.arthas\lib\3.1.7\arthas
[INFO] Try to attach process 4192
[INFO] Attach process 4192 success.
[INFO] arthas-client connect 127.0.0.1 3658
  ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.
 /  O  \ |  .--. ''--.  .--'|  '--'  | /  O  \ '   .-'
|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.
|  | |  ||  |\  \    |  |   |  |  |  ||  | |  |.-'    |
`--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'
  
  
wiki      https://alibaba.github.io/arthas
tutorials https://alibaba.github.io/arthas/arthas-tutorials
version   3.1.7
pid       4192
time      2020-03-15 14:24:57

 

120.1.2. L'installation via les binaires sous Windows

Pour cela, il faut télécharger une archive zip sur Maven Central dont le groupId est com.taobao.arthas et l'artefactId est arthas-packaging :

L'archive peut aussi être téléchargée sur la page des releases d'Arthas : https://github.com/alibaba/arthas/releases

Il faut ensuite décompresser l'archive.

Pour lancer Arthas, il faut exécuter le script as.bat dans le sous-répertoire bin.

 

120.1.3. L'installation via un script sous Linux et Mac

Il est possible de télécharger et d'exécuter le script install.sh proposé par Arthas. Les exemples de cette section sont dans un Ubuntu On Windows (WSL).

Résultat :
jm@L-X1:/mnt/c/temp/arthas$ curl -L https://alibaba.github.io/arthas/install.sh | sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   961  100   961    0     0    752      0  0:00:01  0:00:01 --:--:--   752
downloading... ./as.sh.23
Arthas install successed.
jm@L-X1:/mnt/c/temp/arthas$ ls -al
total 28
drwxrwxrwx 1 jm jm   512 mars  14 18:27 .
drwxrwxrwx 1 jm jm   512 mars  14 18:25 ..
-rwxrwxrwx 1 jm jm 28075 mars  14 18:27 as.sh
jm@L-X1:/mnt/c/temp/arthas$

Ce script peut être placé dans un répertoire quelconque et même déplacé par la suite mais il est pratique dans le rajouter dans la variable système PATH.

Le script requière l'outil unzip.

Résultat :
jm@L-X1:/mnt/c/temp/arthas$ ./as.sh
Error: unzip is not installed. Try to use java -jar arthas-boot.jar

Sur une distribution Ubuntu, il suffit d'exécuter la commande ci-dessous :

Résultat :
jm@L-X1:/mnt/c/temp/arthas$ sudo apt-get install zip


Lors de la première exécution, il faut préciser la version d'Arthas à utiliser et le pid de la JVM à laquelle Arthas va s'attacher.

Résultat :
jm@L-X1:/mnt/c/temp/arthas$ ./as.sh --use-version 3.1.7 829
Arthas script version: 3.1.7
[INFO] JAVA_HOME: /usr/lib/jvm/java-9-openjdk-amd64
updating version 3.1.7 ...
Download arthas from: https://repo1.maven.org/maven2/com/taobao/arthas/arthas-packaging/3.1.7/a
rthas-packaging-3.1.7-bin.zip

curl: (28) Connection timed out after 5001 milliseconds
update fail, ignore this update.
Arthas home: /home/jm/.arthas/lib/3.1.7/arthas
Arthas home is not a directory, please delete it and retry.
jm@L-X1:/mnt/c/temp/arthas$ ./as.sh --use-version 3.1.7 829
Arthas script version: 3.1.7
[INFO] JAVA_HOME: /usr/lib/jvm/java-9-openjdk-amd64
updating version 3.1.7 ...
Download arthas from: https://repo1.maven.org/maven2/com/taobao/arthas/arthas-packaging/3.1.7/a
rthas-packaging-3.1.7-bin.zip
########################################################################100,0%
Archive:  /tmp/temp_3.1.7_1377/arthas-3.1.7-bin.zip
   creating: /tmp/temp_3.1.7_1377/async-profiler/
  inflating: /tmp/temp_3.1.7_1377/arthas-spy.jar
  inflating: /tmp/temp_3.1.7_1377/arthas-agent.jar
  inflating: /tmp/temp_3.1.7_1377/arthas-client.jar
  inflating: /tmp/temp_3.1.7_1377/arthas-boot.jar
  inflating: /tmp/temp_3.1.7_1377/arthas-demo.jar
  inflating: /tmp/temp_3.1.7_1377/install-local.sh
  inflating: /tmp/temp_3.1.7_1377/as.sh
  inflating: /tmp/temp_3.1.7_1377/as.bat
  inflating: /tmp/temp_3.1.7_1377/as-service.bat
  inflating: /tmp/temp_3.1.7_1377/async-profiler/libasyncProfiler-linux-x64.so
  inflating: /tmp/temp_3.1.7_1377/async-profiler/libasyncProfiler-mac-x64.so
  inflating: /tmp/temp_3.1.7_1377/arthas-core.jar
update completed.
Arthas home: /home/jm/.arthas/lib/3.1.7/arthas
Calculating attach execution time...
Attaching to 829 using version /home/jm/.arthas/lib/3.1.7/arthas...
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message trans
form method call failed at JPLISAgent.c line: 884
*** java.lang.instrument ASSERTION FAILED ***: "!errorOutstanding" with message trans
form method call failed at JPLISAgent.c line: 884

 
real    0m3.406s
user    0m0.734s
sys     0m0.234s
Attach success.
telnet connecting to arthas server... current timestamp is 1584124377
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
  ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.
 /  O  \ |  .--. ''--.  .--'|  '--'  | /  O  \ '   .-'
|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.
|  | |  ||  |\  \    |  |   |  |  |  ||  | |  |.-'    |
`--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'
 
 
wiki      https://alibaba.github.io/arthas
tutorials https://alibaba.github.io/arthas/arthas-tutorials
version   3.1.7
pid       829
time      2020-03-13 19:32:56
 
[arthas@829]$

Le script télécharge l'archive zip sur le dépôt Maven Central et la décompresse dans le sous-répertoire .arthas/lib/{version}/arthas du répertoire home de l'utilisateur.

 

120.1.4. L'installation via des packages pour Debian et Fedora

Arthas propose des packages pour Debian et Fedora qu'il est possible de télécharger sur la page des releases : https://github.com/alibaba/arthas/releases.

Pour lancer l'installation sur Debian, il faut utiliser la commande ci-dessous :

Résultat :
$ sudo dpkg -i arthas*.deb

La commande à utiliser pour Debian est :

Résultat :
$ sudo rpm -i arthas*.rpm
 

 

120.1.5. La mise à jour

Lors du lancement d'Arthas via le jar arthas-boot.jar, une vérification est faite sur l'existence d'une nouvelle version et si c'est le cas, elle est automatiquement téléchargée et utilisée.

Résultat :
C:\java>java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.1.7
[INFO] Found existing java process, please choose one and hit RETURN.
* [1]: 20032 arthas-demo.jar
 
[INFO] local lastest version: 3.1.7, remote lastest version: 3.2.0, try to download from remote
[INFO] Start download arthas from remote server: https://repo1.maven.org/maven2/com/taobao/arth
as/arthas-packaging/3.2.0/arthas-packaging-3.2.0-bin.zip
[INFO] File size: 10,82 MB, downloaded size: 649,35 KB, downloading ...
[INFO] File size: 10,82 MB, downloaded size: 1,14 MB, downloading ...
[INFO] File size: 10,82 MB, downloaded size: 1,48 MB, downloading ...
...
[INFO] File size: 10,82 MB, downloaded size: 10,16 MB, downloading ...
[INFO] File size: 10,82 MB, downloaded size: 10,52 MB, downloading ...
[INFO] Download arthas success.
[INFO] arthas home: C:\Users\jm\.arthas\lib\3.2.0\arthas
[INFO] Try to attach process 20032

 

120.1.6. La désinstallation

Il faut supprimer les sous-répertoires .arthas, logs/arthas et logs/arthas-cache dans le répertoire home de l'utilisateur.

Exemple sous Linux :

Résultat :
$ rm -rf ~/.arthas/
 
$ rm -rf ~/logs/arthas/
 

 

120.2. Le démarrage

Pour s'éviter des ennuis, il faut utiliser le même utilisateur pour lancer l'application dans une JVM et Arthas ou utiliser un utilisateur qui a les mêmes privilèges.

Au cas où Arthas n'arrive pas à s'attacher à la JVM, il faut consulter les logs d'Arthas qui sont dans le sous-répertoire logs/arthas du répertoire home de l'utilisateur.

Le démarrage d'Arthas peut se faire de plusieurs manières.

Lorsque le client Arthas se connecte à la JVM, des messages sont affichés dans la console :

Résultat :
Sat Mar 14 21:52:07 CET 2020 com.taobao.arthas.agent.ArthasClassloader@27254f36 JM.Log:INFO Log
 root path: C:\Users\jm\logs\
Sat Mar 14 21:52:07 CET 2020 com.taobao.arthas.agent.ArthasClassloader@27254f36 JM.Log:INFO Set
 arthas log path: C:\Users\jm\logs\arthas

 

120.2.1. Le démarrage avec le jar arthas-boot.jar

Pour lancer Arthas, il suffit d'exécuter le fichier jar arthas-boot.jar téléchargé

Résultat :
java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.1.7
[INFO] Found existing java process, please choose one and hit RETURN.
* [1]: 6852 arthas-demo.jar
 

Arthas affiche les JVM locales en cours d'exécution et il est possible de sélectionner celle à laquelle le client Arthas doit se connecter. Celle précédée d'une étoile est celle sélectionnée par défaut en appuyer simplement sur la touche « Entrée ».

Pour sélectionner une JVM en particulier sur suffit de saisir le numéro entre crochets et d'appuyer sur la touche « Entrée ».

Résultat :
[INFO] arthas home: C:\Users\jm\.arthas\lib\3.1.7\arthas
[INFO] Try to attach process 6852
[INFO] Attach process 6852 success.
[INFO] arthas-client connect 127.0.0.1 3658
  ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.
 /  O  \ |  .--. ''--.  .--'|  '--'  | /  O  \ '   .-'
|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.
|  | |  ||  |\  \    |  |   |  |  |  ||  | |  |.-'    |
`--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'
 
 
wiki      https://alibaba.github.io/arthas
tutorials https://alibaba.github.io/arthas/arthas-tutorials
version   3.1.7
pid       6852
time      2020-02-23 18:31:28


Si Arthas n'arrive pas à détecter de JVM, alors il s'arrête avec un message d'erreur.

Résultat :
C:\java>java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.1.7
[INFO] Can not find java process. Try to pass <pid> in command line.
Please select an available pid.


Il est possible de passer l'option -h ou --help à Arthas pour obtenir le détail des options utilisables.

Résultat :
C:\java> java -jar arthas-boot.jar -h
[INFO] arthas-boot version: 3.1.7
Usage: arthas-boot [--repo-mirror <value>] [--session-timeout <value>]
       [--use-version <value>] [--http-port <value>] [--arthas-home <value>]
       [-h] [--target-ip <value>] [--telnet-port <value>] [-c <value>]
       [--tunnel-server <value>] [--agent-id <value>] [--width <value>]
       [--versions] [--height <value>] [--use-http] [--stat-url <value>]
       [--attach-only] [-f <value>] [-v] [pid]
 
Bootstrap Arthas
 
EXAMPLES:
  java -jar arthas-boot.jar <pid>
  java -jar arthas-boot.jar --target-ip 0.0.0.0
  java -jar arthas-boot.jar --telnet-port 9999 --http-port -1
  java -jar arthas-boot.jar --tunnel-server 'ws://192.168.10.11:7777/ws'
  java -jar arthas-boot.jar --tunnel-server 'ws://192.168.10.11:7777/ws'
--agent-id bvDOe8XbTM2pQWjF4cfw
  java -jar arthas-boot.jar --stat-url 'http://192.168.10.11:8080/api/stat'
  java -jar arthas-boot.jar -c 'sysprop; thread' <pid>
  java -jar arthas-boot.jar -f batch.as <pid>
  java -jar arthas-boot.jar --use-version 3.1.7
  java -jar arthas-boot.jar --versions
  java -jar arthas-boot.jar --session-timeout 3600
  java -jar arthas-boot.jar --attach-only
  java -jar arthas-boot.jar --repo-mirror aliyun --use-http
WIKI:
  https://alibaba.github.io/arthas
 

Arthas propose de nombreuses options utilisables à son démarrage :

Option

Rôle

--target-ip

Adresse IP de la JVM cible : la valeur par défaut est 127.0.0.1 (localhost)

--telnet-port

Le port telnet utilisé par la JVM pour communiquer avec le client : la valeur par défaut est 3658

--http-port

Le port http utilisé par la JVM pour accéder à la console web : la valeur par défaut est 8563

--use-version

Utiliser la version précisée d'Arthas

--use-http

Utiliser HTTP au lieu d'HTTPS utilisé par défaut pour les téléchargements

-v, --verbose

Afficher des informations de debug

-f, --batch-file <value>

Exécuter le script précisé comme valeur

--repo-mirror <value>

Utiliser le dépôt Maven précisé comme valeur

--session-timeout <value>

Définir le timeout de la session : par défaut 1800 (30 minutes)

--arthas-home <value>

Définir le répertoire qui contient Arthas

-h, --help

Afficher l'aide en ligne

-c, --command <value>

Exécuter la commande précisée comme valeur. Plusieurs commandes doivent être séparées avec un point-virgule

--tunnel-server <value>  
--agent-id <value>  
--width <value>

Définir la longueur du terminal Arthas

--versions

Afficher la liste des versions d'Arthas locales et téléchargeables

--height <value>

Définir la hauteur du terminal Arthas

--stat-url <value>  
--attach-only

S'attacher à la JVM sans s'y connecter

<pid>

Préciser le pid de la JVM


L'option --versions affiche les versions locales et celles qu'il est possible de télécharger.

Résultat :
java -jar arthas-boot.jar --versions
[INFO] arthas-boot version: 3.1.7
Local versions:
 3.1.7
Remote versions:
 3.1.7
 3.1.6
 3.1.5
 3.1.4
 3.1.3
 3.1.2
 3.1.1
 3.1.0
 3.0.5
 3.0.4
 3.0.3
 3.0.0-RC 

 

120.2.2. Le démarrage avec le script as.sh/as.bat

Il est possible de démarrer Arthas en utilisant le script as.sh ou as.bat contenu dans l'archive d'arthas dans le sous-répertoire .arthas dans le répertoire de l'utilisateur.

Le script attend en paramètre le pid de la JVM : si celui-ci n'est pas fourni un message d'erreur s'affiche

Résultat :
C:\Users\jm\.arthas\lib\3.1.7\arthas> as.bat
Example:
  as.bat 452
  as.bat 452 --ignore-tools # for jdk 9/10/11
 
Need the pid argument, you can run jps to list all java process ids.
exit était inattendu.
 
C:\Users\jm\.arthas\lib\3.1.7\arthas>

Comme indiqué dans le message, il est possible d'utiliser la commande jps fournie dans le JDK pour trouver le pid de la JVM concernée.

Résultat :
C:\Users\jm\.arthas\lib\3.1.7\arthas> jps
8224 Jps
4856 jar
 
C:\Users\jm\.arthas\lib\3.1.7\arthas> as.bat 4856
JAVA_HOME: C:\Program Files\Java\jdk1.8.0_202
telnet port: 3658
http port: 8563
 
  ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.
 /  O  \ |  .--. ''--.  .--'|  '--'  | /  O  \ '   .-'
|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.
|  | |  ||  |\  \    |  |   |  |  |  ||  | |  |.-'    |
`--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'
 
 
wiki      https://alibaba.github.io/arthas
tutorials https://alibaba.github.io/arthas/arthas-tutorials
version   3.1.7
pid       4856
time      2020-03-13 16:15:28

 

120.2.3. L'utilisation de la console CLI

Après le démarrage d'Arthas et la connexion à la JVM choisie, un prompt est affiché et attend la saisie d'une commande.

Résultat :
C:\java> java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.1.7
[INFO] Process 14128 already using port 3658
[INFO] Process 14128 already using port 8563
[INFO] Found existing java process, please choose one and hit RETURN.
* [1]: 14128 arthas-demo.jar
 
[INFO] arthas home: C:\Users\jm\.arthas\lib\3.1.7\arthas
[INFO] The target process already listen port 3658, skip attach.
[INFO] arthas-client connect 127.0.0.1 3658
  ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.
 /  O  \ |  .--. ''--.  .--'|  '--'  | /  O  \ '   .-'
|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.
|  | |  ||  |\  \    |  |   |  |  |  ||  | |  |.-'    |
`--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'
 
 
wiki      https://alibaba.github.io/arthas
tutorials https://alibaba.github.io/arthas/arthas-tutorials
version   3.1.7
pid       14128
time      2020-02-14 00:06:47


[arthas@14128]$

Il est alors possible de saisir des commandes qui seront exécutées en fonction des besoins.

La touche tabulation peut être utilisée après avoir saisie un ou plusieurs caractères pour aider à la complétion de différents éléments :

 

120.3. Les fonctionnalités

La console propose une interface en ligne de commandes (CLI) qui permet d'envoyer des commandes au serveur Arthas exécuté dans la JVM cible.

Lors de l'exécution de certaines commandes, Arthas affiche un message qui indique le nombre d'éléments impactés (classes, méthodes, lignes, ...) et le temps utilisé.

Résultat :
Affect(class-cnt:7 , method-cnt:13) cost in 94 ms.

 

120.3.1. Les fonctionnalités de base

Le CLI d'Arthas propose plusieurs fonctionnalités de base dont certaines sont inspirées par des commandes standard sous Unix.

Commande

Rôle

help

Afficher l'aide

cls

Effacer l'écran

cat

Concaténer / afficher un fichier

grep

Filtrer sur un motif

pwd

Renvoyer le répertoire courant

session

Afficher l'identifiant de la session

reset

Réinitialiser les classes qui ont été enrichies pour permettre leur instrumentation pour qu'elles reviennent à leur code d'origine

version

Afficher la version du CLI

history

Afficher l'historique des commandes

quit/exit

Terminer la session courante

stop/shutdown

Terminer le serveur Arthas : toutes les sessions sont terminées, tous les clients connectés au serveur sont déconnectés

keymap

Afficher les raccourcis clavier

options

Afficher les options globales d'Arthas et leurs valeurs

 

120.3.1.1. Quitter Arthas

Par défaut au bout de 30 minutes, la session entre le client et le serveur Arthas est fermée.

Résultat :
[arthas@17512]$ session (82a8208d-66fc-4b0a-95b9-1f949948bb1c) is closed because session is ina
ctive for 30 min(s).

Pour terminer la session et quitter Arthas, plusieurs commandes peuvent être utilisées.

Pour quitter la console Arthas, il faut utiliser la commande quit ou la commande exit. Ces deux commandes terminent la connexion avec le serveur sur la JVM en cours de monitoring et arrête la console. Attention dans ce cas, le code instrumenté n'est pas réinitialisé, le serveur sur la JVM est toujours en cours d'exécution et le port utilisé n'est pas libéré. Cela permet de connecter une autre console Arthas.

Pour arrêter complètement Arthas, le serveur et la console, il faut utiliser la commande shutdown ou la commande stop. Lors de l'invocation de l'une de ces deux méthodes, toutes les méthodes instrumentées pour capturer des informations sont réinitialisées pour revenir à leur code d'origine. Il est donc important de les utiliser notamment en production si la JVM doit poursuivre son exécution.

 

120.3.1.2. La commande cat

La commande cat a un rôle similaire à celle d'Unix : elle permet de concaténer et d'afficher le contenu d'un ou plusieurs fichiers.

La syntaxe de la commande cat est de la forme :

cat [--encoding <value>] [-h] files...

La commande cat possède plusieurs paramètres dont :

Paramètre

Rôle

--encoding <value>

Préciser le jeu d'encodage de caractères des fichiers


Résultat :
[arthas@14128]$ cat c:/temp/test.txt
ligne1
ligne2
ligne3[arthas@14128]$

 

120.3.1.3. La commande grep

Le commande grep a un rôle similaire à celle d'Unix : elle permet de filtrer les informations affichées par une commande à la console.

La syntaxe de la commande grep est de la forme :

grep [-A <value>] [-B <value>] [-C <value>] [-h] [-i] [-v] [-n] [-m <value>] [-e] [--trim-end <value>] pattern

La commande grep possède plusieurs paramètres dont :

Paramètre

Rôle

-i, --ignore-case

Filtrer sans tenir compte de la casse. Par défaut, la casse est prise en compte

-v, --invert-match

Filtrer les lignes qui ne respectent pas le motif

-n, --line-number

Afficher un numéro à chaque ligne

-m, --max-count <value>

Limiter le nombre de lignes affichées à celui précisé

-e, --regex

Activer l'utilisation d'une expression régulière

--trim-end <value>

Supprimer les espaces à la fin de chaque ligne. Valeur par défaut : true

<pattern>

Le motif à appliquer


Résultat :
[arthas@14128]$ thread 10 | grep fr.test
    at fr.jmdoudoux.dej.Service.traiter(Service.java:12)
    at fr.jmdoudoux.dej.ThreadService.run(ThreadService.java)
[arthas@14128]$

 

120.3.1.4. La commande pwd

La commande pwd renvoie le chemin du répertoire courant, celui dans lequel la CLI Arthas a été démarrée.

Résultat :
[arthas@14128]$ pwd
C:\java\Arthas-demo
[arthas@14128]$

 

120.3.1.5. La commande options

La commande options permet de voir et de modifier la valeur des options globales.

La syntaxe de la commande options est de la forme :

options [-h] [options-name] [options-value]

La commande options possède plusieurs paramètres dont :

Paramètre

Rôle

<options-name>

Le nom de l'option

<options-value>

La nouvelle valeur de l'option


Les options globales utilisables dans Arthas sont :

Nom

Valeur par défaut

Description

unsafe

false

Permettre d'utiliser des proxys sur les classes du JDK. A utiliser avec précaution car cela peut engendrer un crash de la JVM

dump

false

Effectuer un dump des classes enrichies dans des fichiers dont le chemin sera affiché dans la console

batch-re-transform

true

json-format

false

Demander à ce que le résultat de l'exécution de commandes soit en JSON

disable-sub-class

false

Demander d'inclure les sous-classes lors de la recherche de correspondance sur le nom de classes

debug-for-asm

false

Demander le niveau de log debug pour ASM

save-result

false

Demander l'enregistrement des exécutions de commandes dans le fichier logs/arthas-cache/result.log dans le sous-répertoire home de l'utilisateur

job-timeout

1d

Durée du timeout par défaut des tâches exécutées en arrière-plan. Exemple : 1d, 2h, 5m, 10s


Sans paramètres, la commande options affiche la valeur de toutes les options globales.

Résultat :
[arthas@14128]$ options
 LEVEL TYPE     NAME           VALUE   SUMMARY                 DESCRIPTION
-----------------------------------------------------------------------------------------------
 0     boolean  unsafe         false   Option to support syst  This option enables to proxy fun
                                       em-level class          ctionality of JVM classes. Due t
                                                               o serious security risk a JVM cr
                                                               ash is possibly be introduced. D
                                                               o not ctivate it unless you are 
                                                               able to manage.
 1     boolean  dump           false   Option to dump the enh  This option enables the enhanced
                                       anced classes            classes to be dumped to externa
                                                               l file for further de-compilatio
                                                               n and analysis.
 1     boolean  batch-re-tran  true    Option to support batc  This options enables to reTransf
                sform                  h reTransform Class     orm classes with batch mode.
 2     boolean  json-format    false   Option to support JSON  This option enables to format ob
                                       format of object outpu  ject output with JSON when -x op
                                       t                       tion selected.
 1     boolean  disable-sub-c  false   Option to control incl  This option disable to include s
                lass                   ude sub class when cla  ub class when matching class.
                                       ss matching
 1     boolean  debug-for-asm  false   Option to print DEBUG   This option enables to print DEB
                                       message if ASM is invo  UG message of ASM for each metho
                                       lved                    d invocation.
 1     boolean  save-result    false   Option to print comman  This option enables to save each
                                       d's result to log file   command's result to log file, w
                                                               hich path is ${user.home}/logs/a
                                                               rthas-cache/result.log.
 2     String   job-timeout    1d      Option to job timeout   This option setting job timeout,
                                                               The unit can be d, h, m, s for d
                                                               ay, hour, minute, second. 1d is 
                                                               one day in default
 1     boolean  print-parent-  true    Option to print all fi  This option enables print files 
                fields                 leds in parent class    in parent class, default value t
                                                               rue.
[arthas@14128]$

Pour obtenir uniquement une seule option, il suffit de préciser son nom en paramètre.

Résultat :
[arthas@14128]$ options save-result
 LEVEL   TYPE     NAME           VALUE   SUMMARY                 DESCRIPTION
-----------------------------------------------------------------------------------------------
 1       boolean  save-result    false   Option to print comman  This option enables to save ea
                                         d's result to log file  ch command's result to log fil
                                                                 e, which path is ${user.home}/
                                                                 logs/arthas-cache/result.log.
[arthas@14128]$

Pour modifier la valeur d'une option, il suffit de préciser son nom et sa nouvelle valeur en paramètre.

Résultat :
[arthas@14128]$ options save-result true
 NAME         BEFORE-VALUE  AFTER-VALUE
----------------------------------------
 save-result  false         true
[arthas@12512]$ options save-result
 LEVEL   TYPE     NAME           VALUE   SUMMARY                 DESCRIPTION
-----------------------------------------------------------------------------------------------
 1       boolean  save-result    true    Option to print comman  This option enables to save ea
                                         d's result to log file  ch command's result to log fil
                                                                 e, which path is ${user.home}/
                                                                 logs/arthas-cache/result.log. 
[arthas@14128]$

 

120.3.1.6. La commande help

La commande help affiche l'aide.

La syntaxe de la commande help est de la forme :

help [-h] [cmd]

La commande help possède plusieurs paramètres dont :

Paramètre

Rôle

<cmd>

Nom de la commande dont on souhaite obtenir l'aide


Sans option, la commande help affiche la liste des commandes utilisables.

Résultat :
[arthas@14128]$ help
 NAME         DESCRIPTION
 help         Display Arthas Help
 keymap       Display all the available keymap for the specified connection.
 sc           Search all the classes loaded by JVM
 sm           Search the method of classes loaded by JVM
 classloader  Show classloader info
 jad          Decompile class
...

Pour obtenir l'aide pour une commande particulière, il faut préciser le nom de la commande en paramètre de la commande help.

Résultat :
[arthas@14128]$ help version
 USAGE:
   version [-h]
 
 SUMMARY:
   Display Arthas version
 
 OPTIONS:
 -h, --help                           this help
[arthas@14128]$

De manière équivalente, il est possible d'utiliser la commande concernée en lui passant en paramètre -h.

Résultat :
[arthas@14128]$ version -h
 USAGE:
   version [-h]
 
 SUMMARY:
   Display Arthas version
 
 OPTIONS:
 -h, --help                           this help
 
[arthas@14128]$

 

120.3.1.7. La commande cls

La commande cls efface l'écran et repositionne le prompt en haut de l'écran.

La syntaxe de la commande cls est de la forme :

cls [-h]

 

120.3.1.8. La commande session

La commande session affiche l'identifiant de la session.

La syntaxe de la commande session est de la forme :

session [-h]

Résultat :
[arthas@14128]$ session
 Name        Value
--------------------------------------------------
 JAVA_PID    14128
 SESSION_ID  f69eeca0-0d2b-4285-904e-0b9e8572adec
[arthas@14128]$

 

120.3.1.9. La commande reset

La commande reset réinitialise les classes qui ont été enrichies pour permettre leur instrumentation afin qu'elles reviennent à leur code d'origine.

La syntaxe de la commande reset est de la forme :

reset [-h] [-E] [class-pattern]

La commande reset possède plusieurs paramètres dont :

Paramètre

Rôle

-E, --regex

Activer l'utilisation d'une expression régulière. Par défaut, seul le caractère * est utilisable

<class-pattern>

Motif pour le nom de classe


Sans paramètre, la commande réinitialise toutes les classes instrumentées

Résultat :
[arthas@14128]$ reset
Affect(class-cnt:6 , method-cnt:0) cost in 84 ms.
[arthas@14128]$

Il est possible de préciser en paramètre la classe concernée

Résultat :
[arthas@14128]$ reset fr.jmdoudoux.dej.Compteur
Affect(class-cnt:1 , method-cnt:0) cost in 50 ms.
[arthas@14128]$

 

120.3.1.10. La commande version

La commande affiche la version de la CLI.

Résultat :
[arthas@14128]$ version
3.1.7
[arthas@14128]$

 

120.3.1.11. La commande history

La commande history affiche l'historique des commandes.

La syntaxe de la commande history est de la forme :

history [-c <value>] [-h] [n]

La commande history possède plusieurs paramètres dont :

Paramètre

Rôle

-c, --clear <value>

Effacer l'historique

<n>

Nombre de commandes de l'historique à afficher


Sans option, la commande history affiche l'intégralité des commandes saisies.

Résultat :
[arthas@14128]$ history
    1  dashboard
    2  dashboard
    3  stop
    4  dashboard
    5  getstatic fr.jmdoudoux.dej.Main valeur
    6  vmoption
[arthas@14128]$

 

120.3.1.12. La commande keymap

La commande affiche les raccourcis clavier utilisables.

La syntaxe de la commande keymap est de la forme :

keymap [-h]

Résultat :
[arthas@14128]$ keymap
      
 Shortcut                    Description                Name
----------------------------------------------------------------------------------------------
 "\C-a"            Ctrl + a                    beginning-of-line
 "\C-e"            Ctrl + e                    end-of-line
 "\C-f"            Ctrl + f                    forward-word
 "\C-b"            Ctrl + b                    backward-word
 "\e[D"            Left arrow                  backward-char
 "\e[C"            Right arrow                 forward-char
 "\e[A"            Up arrow                    history-search-backward
 "\e[B"            Down arrow                  history-search-forward
 "\C-h"            Ctrl + h                    backward-delete-char
 "\C-?"            Ctrl + ?                    backward-delete-char
 "\C-u"            Ctrl + u                    undo
 "\C-d"            Ctrl + d                    delete-char
 "\C-k"            Ctrl + k                    kill-line
 "\C-i"            Ctrl + i                    complete
 "\C-j"            Ctrl + j                    accept-line
 "\C-m"            Ctrl + m                    accept-line
 "\C-w"            Ctrl + w                    backward-delete-word
 "\C-x\e[3~"       "\C-x\e[3~"                 backward-kill-line
 "\e\C-?"          "\e\C-?"                    backward-kill-word
 "\e[1~"           "\e[1~"                     beginning-of-line
 "\e[4~"           "\e[4~"                     end-of-line
 "\e[5~"           "\e[5~"                     beginning-of-history
 "\e[6~"           "\e[6~"                     end-of-history
 "\e[3~"           "\e[3~"                     delete-char
 "\e[2~"           "\e[2~"                     quoted-insert
 "\e[7~"           "\e[7~"                     beginning-of-line
 "\e[8~"           "\e[8~"                     end-of-line
 "\eOH"            "\eOH"                      beginning-of-line
 "\eOF"            "\eOF"                      end-of-line
 "\e[H"            "\e[H"                      beginning-of-line
 "\e[F"            "\e[F"                      end-of-line
[arthas@14128]$

 

120.3.2. Les pipes

Arthas propose un support des pipes de manière similaire aux shells sous Unix. Cela permet d'envoyer le résultat de la commande qui précède le pipe en entrée de la commande qui le suit. Les commandes utilisables après le pipe sont grep, plaintext et wc -l.

Résultat :
[arthas@14128]$ sm java.lang.String * | grep 'index'
java.lang.String indexOf(Ljava/lang/String;I)I
java.lang.String indexOf(Ljava/lang/String;)I
java.lang.String indexOf(II)I
java.lang.String indexOf(I)I
java.lang.String indexOf([CII[CIII)I
java.lang.String indexOf([CIILjava/lang/String;I)I
java.lang.String indexOfSupplementary(II)I
[arthas@14128]$ sm java.lang.String * | wc -l
94
[arthas@14128]$

 

120.3.3. Les fonctionnalités concernant la JVM

Arthas propose plusieurs commandes relatives à la JVM :

Commande

Rôle

dashboard

Afficher un tableau de bord sur l'activité de la JVM

thread

Afficher des informations sur les threads

jvm

Afficher des informations sur la JVM

sysprop

Afficher/modifier les propriétés systèmes de la JVM

sysenv

Afficher les variables d'environnement système

vmoption

Afficher/modifier les options de diagnostic de la JVM

logger

Afficher des informations sur les loggers, modifier le niveau de gravité d'un logger

mbean

Afficher les informations d'un MBean

heapdump

Créer un dump du heap dans un fichier au format hprof

 

120.3.3.1. La commande dashboard

La commande dashboard affiche un tableau de bord contenant des statistiques en temps réel sur certaines activités de la JVM : threads, mémoire, GC et des informations sur le système.

Les informations sont réaffichées toutes les 5 secondes par défaut. Il faut utiliser la combinaison de touches Ctrl+C pour arrêter le rafraîchissement.

Résultat :
ID    NAME                        GROUP        PRIORITY STATE    %CPU    TIME   INTERRUP DAEMON
10    Service_1                   main         5        TIMED_WA 100     2:4    false    false
14    AsyncAppender-Worker-arthas system       5        WAITING  0       0:0    false    true
5     Attach Listener             system       5        RUNNABLE 0       0:0    false    true
3     Finalizer                   system       8        WAITING  0       0:0    false    true
2     Reference Handler           system       10       WAITING  0       0:0    false    true
11    Service_2                   main         5        TIMED_WA 0       2:2    false    false
4     Signal Dispatcher           system       9        RUNNABLE 0       0:0    false    true
31    Timer-for-arthas-dashboard- system       10       RUNNABLE 0       0:0    false    true
29    as-command-execute-daemon   system       10       TIMED_WA 0       0:0    false    true
16    job-timeout                 system       5        TIMED_WA 0       0:0    false    true
1     main                        main         5        WAITING  0       0:0    false    false
17    nioEventLoopGroup-2-1       system       10       RUNNABLE 0       0:0    false    false
21    nioEventLoopGroup-2-2       system       10       RUNNABLE 0       0:0    false    false
26    nioEventLoopGroup-2-3       system       10       RUNNABLE 0       0:0    false    false
28    nioEventLoopGroup-2-4       system       10       RUNNABLE 0       0:0    false    false
18    nioEventLoopGroup-3-1       system       10       RUNNABLE 0       0:0    false    false
Memory                  used   total   max     usage   GC
heap                    34M    109M    1799M   1,91%   gc.ps_scavenge.count        2224
ps_eden_space           5M     23M     673M    0,87%   gc.ps_scavenge.time(ms)     4679
ps_survivor_space       160K   512K    512K    31,25%  gc.ps_marksweep.count       0
ps_old_gen              28M    85M     1349M   2,10%   gc.ps_marksweep.time(ms)    0
nonheap                 25M    28M     -1      90,26%
code_cache              3M     5M      240M    1,61%
metaspace               19M    19M     -1      96,51%
compressed_class_space  2M     2M      1024M   0,23%
Runtime
os.name                                                Windows 10
os.version                                             10.0
java.version                                           1.8.0_202
java.home                                              C:\Program Files\Java\jdk1.8.0_202\jre
systemload.average                                     -1,00
processors                                             4
uptime                                                 31006s

Les informations sont regroupées par thème

En haut du tableau de bord, une liste des threads en cours d'exécution, classés en fonction de l'utilisation du CPU, avec quelques informations sont affichées en colonnes :

Elles sont affichées en colonnes :

La section suivante concerné la mémoire : est découpée en deux parties, l'une concernant la mémoire de la JVM (heap (eden/survivor/old) et hors heap) et l'autre concernant le GC (statistiques sur le nombre et le time des collections dans la young et la old).

La dernière section affiche des informations de base sur l'environnement.

 

120.3.3.2. La commande heapdump

La commande heapdump permet de créer un fichier binaire au hprof du heap de la JVM.

Sans option, la commande heapdump créé un fichier dans le répertoire temporaire

Résultat :
[arthas@17512]$ heapdump
Dumping heap to C:\Users\jm\AppData\Local\Temp\heapdump2020-01-17-18-062141170027159928142.hpro
f...
Heap dump file created
[arthas@17512]$

L'option --live, la commande heapdump ne dump que les objets en cours d'utilisation.

Résultat :
[arthas@17512]$ heapdump
Dumping heap to C:\Users\jm\AppData\Local\Temp\heapdump2020-01-17-18-062141170027159928142.hpro
f...
Heap dump file created
[arthas@17512]$

Il est aussi possible de préciser le nom du fichier qui va contenir le dump.

Résultat :
[arthas@17512]$ heapdump c:/temp/dump.hprof
Dumping heap to c:/temp/dump.hprof...
Heap dump file created
[arthas@17512]$

 

120.3.3.3. La commande thread

La commande thread permet d'obtenir des informations sur les threads et leur stacktrace.

La syntaxe de la commande thread est de la forme :

thread [-h] [-b] [-i <value>] [--state <value>] [-n <value>] [id]

La commande thread possède plusieurs paramètres :

Paramètre

Rôle

Id

Id du thread dans la JVM

-n <value>

Afficher les nb threads les plus occupés avec leur stacktrace

-b

Identifier les threads qui bloquent les autres

-i <value>

Préciser un intervalle de temps en ms pour collecter les données utiles au calcul du ratio CPU

--state <value>

N'afficher que les threads dont le statut est précisé


Sans paramètre, la commande thread affiche la liste des threads.

Résultat :
[arthas@11516]$ thread
Threads Total: 15, NEW: 0, RUNNABLE: 6, BLOCKED: 0, WAITING: 5, TIMED_WAITING: 4, TERMINATED: 0
ID   NAME                        GROUP       PRIORITY STATE    %CPU    TIME     INTERRUP DAEMON
14   AsyncAppender-Worker-arthas system      5        WAITING  0       0:0      false    true
5    Attach Listener             system      5        RUNNABLE 0       0:0      false    true
3    Finalizer                   system      8        WAITING  0       0:0      false    true
2    Reference Handler           system      10       WAITING  0       0:0      false    true
10   Service_1                   main        5        TIMED_WA 0       0:2      false    false
11   Service_2                   main        5        TIMED_WA 0       0:4      false    false
4    Signal Dispatcher           system      9        RUNNABLE 0       0:0      false    true
22   as-command-execute-daemon   system      10       RUNNABLE 0       0:0      false    true
16   job-timeout                 system      5        TIMED_WA 0       0:0      false    true
1    main                        main        5        WAITING  0       0:0      false    false
17   nioEventLoopGroup-2-1       system      10       RUNNABLE 0       0:0      false    false
21   nioEventLoopGroup-2-2       system      10       RUNNABLE 0       0:0      false    false
18   nioEventLoopGroup-3-1       system      10       RUNNABLE 0       0:0      false    false
19   pool-1-thread-1             system      5        TIMED_WA 0       0:0      false    false
20   pool-2-thread-1             system      5        WAITING  0       0:0      false    false
Affect(row-cnt:0) cost in 111 ms.
[arthas@11516]$

Le calcul du ration CPU utilise lui-même du CPU : pour le réduire il est possible d'augmenter l'intervalle de temps de mesure en ms avec option -i.

Résultat :
[arthas@10552]$ thread -i 2000
Threads Total: 15, NEW: 0, RUNNABLE: 6, BLOCKED: 0, WAITING: 5, TIMED_WAITING: 4, TERMINATED: 0
ID   NAME                        GROUP       PRIORITY STATE    %CPU    TIME     INTERRUP DAEMON
11   Service_2                   main        5        TIMED_WA 54      0:3      false    false
10   Service_1                   main        5        TIMED_WA 45      0:2      false    false
14   AsyncAppender-Worker-arthas system      5        WAITING  0       0:0      false    true
5    Attach Listener             system      5        RUNNABLE 0       0:0      false    true
3    Finalizer                   system      8        WAITING  0       0:0      false    true
2    Reference Handler           system      10       WAITING  0       0:0      false    true
4    Signal Dispatcher           system      9        RUNNABLE 0       0:0      false    true
22   as-command-execute-daemon   system      10       RUNNABLE 0       0:0      false    true
16   job-timeout                 system      5        TIMED_WA 0       0:0      false    true
1    main                        main        5        WAITING  0       0:0      false    false
17   nioEventLoopGroup-2-1       system      10       RUNNABLE 0       0:0      false    false
21   nioEventLoopGroup-2-2       system      10       RUNNABLE 0       0:0      false    false
18   nioEventLoopGroup-3-1       system      10       RUNNABLE 0       0:0      false    false
19   pool-1-thread-1             system      5        TIMED_WA 0       0:0      false    false
20   pool-2-thread-1             system      5        WAITING  0       0:0      false    false
Affect(row-cnt:0) cost in 2006 ms.

L'option -n permet d'afficher la stacktrace des n (fournis comme valeur de l'option -n) threads les plus consommateur en CPU.

Résultat :
 [arthas@10552]$ thread -i 3000 -n 2
"Service_1" Id=10 cpuUsage=66% TIMED_WAITING
    at java.lang.Thread.sleep(Native Method)
    at java.lang.Thread.sleep(Thread.java:340)
    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
    at fr.jmdoudoux.dej.Service.traiter(Service.java:12)
    at fr.jmdoudoux.dej.ThreadService.run(ThreadService.java:24)
 
 
"Service_2" Id=11 cpuUsage=33% TIMED_WAITING
    at java.lang.Thread.sleep(Native Method)
    at java.lang.Thread.sleep(Thread.java:340)
    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
    at fr.jmdoudoux.dej.Service.traiter(Service.java:12)
    at fr.jmdoudoux.dej.ThreadService.run(ThreadService.java:24)
 
 
Affect(row-cnt:0) cost in 3012 ms.

Il est possible d'obtenir la stacktrace d'un thread simple passant son id en paramètre de la commande thread.

Résultat :
[arthas@10552]$ thread 10
"Service_1" Id=10 TIMED_WAITING
    at java.lang.Thread.sleep(Native Method)
    at java.lang.Thread.sleep(Thread.java:340)
    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
    at fr.jmdoudoux.dej.Service.traiter(Service.java:12)
    at fr.jmdoudoux.dej.ThreadService.run(ThreadService.java:24)
 
Affect(row-cnt:0) cost in 7 ms.

L'option -b permet de trouver le ou les threads qui bloquent les autres.

L'option --state permet de n'afficher que les threads qui sont dans le statut précisé.

Résultat :
[arthas@10552]$ thread -state WAITING
Threads Total: 16, NEW: 0, RUNNABLE: 7, BLOCKED: 0, WAITING: 5, TIMED_WAITING: 4, TERMINATED: 0
ID   NAME                        GROUP       PRIORITY STATE    %CPU    TIME     INTERRUP DAEMON
14   AsyncAppender-Worker-arthas system      5        WAITING  0       0:0      false    true
3    Finalizer                   system      8        WAITING  0       0:0      false    true
2    Reference Handler           system      10       WAITING  0       0:0      false    true
1    main                        main        5        WAITING  0       0:0      false    false
20   pool-2-thread-1             system      5        WAITING  0       0:0      false    false
Affect(row-cnt:0) cost in 102 ms.

 

120.3.3.4. La commande jvm

La commande jvm affiche des informations sur la JVM.

Résultat :
[arthas@17512]$ jvm
 RUNTIME
------------------------------------------------------------------------------------- 
 MACHINE-NAME                   17512@L-X1
 JVM-START-TIME                 2020-01-19 00:30:55
 MANAGEMENT-SPEC-VERSION        1.2
 SPEC-NAME                      Java Virtual Machine Specification
 SPEC-VENDOR                    Oracle Corporation
 SPEC-VERSION                   1.8
 VM-NAME                        Java HotSpot(TM) 64-Bit Server VM
 VM-VENDOR                      Oracle Corporation
 VM-VERSION                     25.202-b08
 INPUT-ARGUMENTS                []
 CLASS-PATH                     arthas-demo.jar
 BOOT-CLASS-PATH                C:\Program Files\Java\jdk1.8.0_202\jre\lib\resources.
                                jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\rt.jar
                                ;C:\Program Files\Java\jdk1.8.0_202\jre\lib\sunrsasig
                                n.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jsse
                                .jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jce.j
                                ar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\charset
                                s.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib\jfr.
                                jar;C:\Program Files\Java\jdk1.8.0_202\jre\classes
 LIBRARY-PATH                   C:\Program Files\Java\jdk1.8.0_202\bin;C:\WINDOWS\Sun
                                \Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\outils\cm
                                der;.
 
-------------------------------------------------------------------------------------
 CLASS-LOADING
------------------------------------------------------------------------------------- 
 LOADED-CLASS-COUNT             2429
 TOTAL-LOADED-CLASS-COUNT       2439
 UNLOADED-CLASS-COUNT           10
 IS-VERBOSE                     false
 
-------------------------------------------------------------------------------------
 COMPILATION
------------------------------------------------------------------------------------- 
 NAME                           HotSpot 64-Bit Tiered Compilers
 TOTAL-COMPILE-TIME             3200(ms)
 
-------------------------------------------------------------------------------------  
 GARBAGE-COLLECTORS
------------------------------------------------------------------------------------- 
 PS Scavenge                    2866/3765(ms)
 [count/time]
 PS MarkSweep                   1/118(ms)
 [count/time]
 
-------------------------------------------------------------------------------------  
 MEMORY-MANAGERS
------------------------------------------------------------------------------------- 
 CodeCacheManager               Code Cache
 
 Metaspace Manager              Metaspace
                                Compressed Class Space
 
 PS Scavenge                    PS Eden Space
                                PS Survivor Space
 
 PS MarkSweep                   PS Eden Space
                                PS Survivor Space
                                PS Old Gen
 
-------------------------------------------------------------------------------------  
 MEMORY
------------------------------------------------------------------------------------- 
 HEAP-MEMORY-USAGE              76021760(72,50 MiB)/134217728(128,00 MiB)/1886912512(
 [committed/init/max/used]      1,76 GiB)/32195992(30,70 MiB)
 NO-HEAP-MEMORY-USAGE           21626880(20,63 MiB)/2555904(2,44 MiB)/-1(-1 B)/206968
 [committed/init/max/used]      00(19,74 MiB)
 PENDING-FINALIZE-COUNT         0
 
------------------------------------------------------------------------------------- 
 OPERATING-SYSTEM
------------------------------------------------------------------------------------- 
 OS                             Windows 10
 ARCH                           amd64
 PROCESSORS-COUNT               4
 LOAD-AVERAGE                   -1.0
 VERSION                        10.0
 
------------------------------------------------------------------------------------- 
 THREAD
------------------------------------------------------------------------------------- 
 COUNT                          16
 DAEMON-COUNT                   7
 PEAK-COUNT                     16
 STARTED-COUNT                  20
 DEADLOCK-COUNT                 0
 
------------------------------------------------------------------------------------- 
 FILE-DESCRIPTOR
------------------------------------------------------------------------------------- 
 MAX-FILE-DESCRIPTOR-COUNT      -1
 OPEN-FILE-DESCRIPTOR-COUNT     -1
Affect(row-cnt:0) cost in 39 ms.
[arthas@17512]$

Les informations relatives aux threads sont :

Les informations relatives aux descripteurs de fichiers sont :

 

120.3.3.5. La commande sysprop

La commande sysprop permet d'afficher et de modifier des propriétés systèmes de la JMV.

La syntaxe est de la forme :

sysprop [-h] [property-name] [property-value]

Sans option, la commande sysprop affiche toutes les propriétés systèmes avec leur valeur.

Résultat :
[arthas@17512]$ sysprop
 KEY                   VALUE
-------------------------------------------------------------------------------------
 java.runtime.name     Java(TM) SE Runtime Environment
 sun.boot.library.pat  C:\Program Files\Java\jdk1.8.0_202\jre\bin
 h
 java.vm.version       25.202-b08
 java.vm.vendor        Oracle Corporation
 java.vendor.url       http://java.oracle.com/
 path.separator        ;
 java.vm.name          Java HotSpot(TM) 64-Bit Server VM
 file.encoding.pkg     sun.io
 user.script
 user.country          FR
 sun.java.launcher     SUN_STANDARD
 sun.os.patch.level
 java.vm.specificatio  Java Virtual Machine Specification
 n.name
 user.dir              C:\java\workspace-2018-12-Test\Arthas-demo
 java.runtime.version  1.8.0_202-b08
 JM.LOG.PATH           C:\Users\jm\logs
 java.awt.graphicsenv  sun.awt.Win32GraphicsEnvironment
 java.endorsed.dirs    C:\Program Files\Java\jdk1.8.0_202\jre\lib\endorsed
 os.arch               amd64
 java.io.tmpdir        C:\Users\jm\AppData\Local\Temp\
 line.separator
 
 java.vm.specificatio  Oracle Corporation
 n.vendor
 user.variant
 os.name               Windows 10
 sun.jnu.encoding      Cp1252
 java.library.path     C:\Program Files\Java\jdk1.8.0_202\bin;C:\WINDOWS\Sun\Java\bin
                       ;C:\WINDOWS\system32;C:\WINDOWS;C:\Program Files\Java\jdk1.8.0
                       _202\bin;C:\outils\cmder\bin;C:\Program Files\Git\bin;C:\Progr
                       am Files\Git\usr\bin;C:\Program Files\Git\share\vim\vim74;C:\o
                       utils\cmder\vendor\conemu-maximus5\ConEmu\Scripts;C:\outils\cm
                       der\vendor\conemu-maximus5;C:\outils\cmder\vendor\conemu-maxim
                       us5\ConEmu;C:\Program Files\Java\jdk1.8.0_202\bin;c:\java;C:\P
                       rogram Files (x86)\Common Files\Oracle\Java\javapath;C:\Progra
                       m Files (x86)\EasyPHP-DevServer-14.1VC11\binaries\mysql/bin;c:
                       \outils;C:\java\apache-maven-3.6.0\bin;C:\Program Files (x86)\
                       EasyPHP-DevServer-14.1VC11\binaries\php\php_runningversion;C:\
                       ProgramData\Oracle\Java\javapath;C:\Program Files\Intel\iCLS C
                       lient\;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem
                       ;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\java\apache-an
                       t-1.9.6\bin;;C:\Program Files\Git\cmd;C:\Program Files\PuTTY\;
                       C:\WINDOWS\System32\OpenSSH\;C:\outils\OpenSSL-Win64\bin;C:\Pr
                       ogram Files (x86)\Microsoft VS Code\bin;C:\Program Files\nodej
                       s\;C:\Users\jm\AppData\Roaming\npm;C:\Program Files\Docker Too
                       lbox;C:\Program Files\Intel\WiFi\bin\;C:\outils\cmder;.
 sun.nio.ch.bugLevel
 java.specification.n  Java Platform API Specification
 ame
 java.class.version    52.0
 sun.management.compi  HotSpot 64-Bit Tiered Compilers
 ler
 os.version            10.0
 user.home             C:\Users\jm
 user.timezone         Europe/Paris
 java.awt.printerjob   sun.awt.windows.WPrinterJob
 java.specification.v  1.8
 ersion
 file.encoding         Cp1252
 user.name             jm
 java.class.path       arthas-demo.jar
 java.vm.specificatio  1.8
 n.version
 sun.arch.data.model   64
 java.home             C:\Program Files\Java\jdk1.8.0_202\jre
 sun.java.command      arthas-demo.jar
 java.specification.v  Oracle Corporation
 endor
 user.language         fr
 awt.toolkit           sun.awt.windows.WToolkit
 java.vm.info          mixed mode
 java.version          1.8.0_202
 java.ext.dirs         C:\Program Files\Java\jdk1.8.0_202\jre\lib\ext;C:\WINDOWS\Sun\
                       Java\lib\ext
 sun.boot.class.path   C:\Program Files\Java\jdk1.8.0_202\jre\lib\resources.jar;C:\Pr
                       ogram Files\Java\jdk1.8.0_202\jre\lib\rt.jar;C:\Program Files\
                       Java\jdk1.8.0_202\jre\lib\sunrsasign.jar;C:\Program Files\Java
                       \jdk1.8.0_202\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_
                       202\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_202\jre\lib
                       \charsets.jar;C:\Program Files\Jav a\jdk1.8.0_202\jre\lib\jfr.
                       jar;C:\Program Files\Java\jdk1.8.0_202\jre\classes
 sun.stderr.encoding   cp850
 java.vendor           Oracle Corporation
 file.separator        \
 java.vendor.url.bug   http://bugreport.sun.com/bugreport/
 sun.cpu.endian        little
 sun.io.unicode.encod  UnicodeLittle
 ing
 sun.stdout.encoding   cp850
 sun.desktop           windows
 sun.cpu.isalist       amd64
[arthas@17512]$

Il est possible de préciser la propriété à afficher. La touche tab peut être utilisée pour compléter le nom de la propriété par auto-complétion.

Résultat :
[arthas@17512]$ sysprop java.version
java.version=1.8.0_202
[arthas@17512]$

Il est possible de modifier ou de définir une propriété en précisant en option son nom et sa valeur.

Résultat :
[arthas@17512]$ sysprop | grep ma_propriete
[arthas@17512]$ sysprop ma_propriete false
Successfully changed the system property.
ma_propriete=false
[arthas@17512]$ sysprop | grep ma_propriete
 ma_propriete          false

 

120.3.3.6. La commande sysenv

La commande sysenv affiche les variables d'environnement système.

La syntaxe est de la forme :

sysenv [-h] [env-name]

Sans option, la commande sysenv affiche toutes les variables d'environnement système et leur valeur.

Résultat :
[arthas@17512]$ sysenv

 KEY                   VALUE
-------------------------------------------------------------------------------------
 configsetroot         C:\WINDOWS\ConfigSetRoot
 USERDOMAIN_ROAMINGPR  L-X1
 OFILE
 NO_PROXY              192.168.99.100
 PROCESSOR_LEVEL       6
 ConEmuWorkDrive       C:
 FP_NO_HOST_CHECK      NO
 SESSIONNAME           Console
 ALLUSERSPROFILE       C:\ProgramData
 PROCESSOR_ARCHITECTU  AMD64
 RE
 ConEmuANSI            ON
 GIT_INSTALL_ROOT      C:\Program Files\Git
 PSModulePath          C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\
 SystemDrive           C:
 =ExitCode             00000001
 MAVEN_HOME            C:\java\apache-maven-3.6.0
 
...

Pour n'afficher qu'une seule variable, il suffit de passer son nom en paramètre de la commande.

Résultat :
[arthas@9840]$ sysenv username
username=jm
[arthas@9840]$

Il est possible d'utiliser la touche tab pour invoquer l'auto-complétion sur le nom de la variable

Résultat :
[arthas@9840]$ sysenv USER[tab]
      
USERDOMAIN_ROAMINGPROFILE USERNAME               USERDOMAIN               USERPROFILE
 
[arthas@9840]$ sysenv USER

 

120.3.3.7. La commande vmoption

La commande vmoption permet d'afficher ou de modifier les options de la JVM relatives au diagnostic.

Sans option, la commande vmoption affiche les valeurs des options de diagnostic.

Résultat :
[arthas@6672]$ vmoption
 KEY                         VALUE                 ORIGIN                   WRITEABLE
------------------------------------------------------------------------------------- 
 HeapDumpBeforeFullGC        false                 DEFAULT                  true
 HeapDumpAfterFullGC         false                 DEFAULT                  true
 HeapDumpOnOutOfMemoryError  false                 DEFAULT                  true
 HeapDumpPath                                      DEFAULT                  true
 CMSAbortablePrecleanWaitMi  100                   DEFAULT                  true
 llis
 CMSWaitDuration             2000                  DEFAULT                  true
 CMSTriggerInterval          -1                    DEFAULT                  true
 PrintGC                     false                 DEFAULT                  true
 PrintGCDetails              false                 DEFAULT                  true
 PrintGCDateStamps           false                 DEFAULT                  true
 PrintGCTimeStamps           false                 DEFAULT                  true
 PrintGCID                   false                 DEFAULT                  true
 PrintClassHistogramBeforeF  false                 DEFAULT                  true
 ullGC
 PrintClassHistogramAfterFu  false                 DEFAULT                  true
 llGC
 PrintClassHistogram         false                 DEFAULT                  true
 MinHeapFreeRatio            0                     DEFAULT                  true
 MaxHeapFreeRatio            100                   DEFAULT                  true
 PrintConcurrentLocks        false                 DEFAULT                  true
 UnlockCommercialFeatures    false                 DEFAULT                  true
[arthas@6672]$

Il est possible de n'afficher que l'option passée en paramètre

Résultat :
[arthas@6672]$ vmoption PrintGC
 KEY                         VALUE                ORIGIN                    WRITEABLE
------------------------------------------------------------------------------------- 
 PrintGC                     false                MANAGEMENT                true
[arthas@6672]$

Il est possible de modifier la valeur d'une option en précisant cette valeur à la suite du nom de l'option concernée

Résultat :
[arthas@6672]$ vmoption
PrintGC true
Successfully updated the vm
option.
PrintGC=true
[arthas@6672]$

 

120.3.3.8. La commande mbean

La commande mbean permet d'afficher des informations sur des MBeans.

La syntaxe est de la forme :

mbean [-h] [-i <value>] [-m <value>] [-n <value>] [-E] [name-pattern] [attribute-pattern]

La commande mbean possède plusieurs paramètres optionnels :

Paramètre

Rôle

name-pattern

Motif pour le nom de MBean

attribute-pattern

Motif pour le nom d'attribut

[m]

Afficher les méta informations

[i:]

Définir l'intervalle de temps entre les rafraîchissements de la valeur des attributs (en ms)

[n:]

Nombre de rafraîchissements

[E]

Activer l'utilisation d'une expression régulière pour le nom de l'attribut


Sans paramètre, la commande mbean affiche la liste des MBeans disponibles.

Résultat :
[arthas@12844]$ mbean
java.lang:type=MemoryPool,name=Metaspace
java.lang:type=MemoryPool,name=PS Old Gen
java.lang:type=GarbageCollector,name=PS Scavenge
java.lang:type=MemoryPool,name=PS Eden Space
JMImplementation:type=MBeanServerDelegate
java.lang:type=Runtime
java.lang:type=Threading
java.lang:type=OperatingSystem
java.lang:type=MemoryPool,name=Code Cache
java.nio:type=BufferPool,name=direct
java.lang:type=Compilation
java.lang:type=MemoryManager,name=CodeCacheManager
java.lang:type=MemoryPool,name=Compressed Class Space
java.lang:type=Memory
java.nio:type=BufferPool,name=mapped
java.util.logging:type=Logging
java.lang:type=MemoryPool,name=PS Survivor Space
java.lang:type=ClassLoading
java.lang:type=MemoryManager,name=Metaspace Manager
com.sun.management:type=DiagnosticCommand
java.lang:type=GarbageCollector,name=PS MarkSweep
com.sun.management:type=HotSpotDiagnostic
[arthas@12844]$

Par défaut, en passant en paramètre de la commande mbean le nom d'un MBean, toutes les propriétés du MBean sont affichées avec leur valeur.

Résultat :
 [arthas@12844]$ mbean java.lang:type=ClassLoading
 NAME                   VALUE
----------------------------------------------------
 Verbose                false
 LoadedClassCount       3969
 UnloadedClassCount     10
 TotalLoadedClassCount  3979
 ObjectName             java.lang:type=ClassLoading

Il est possible d'utiliser le caractère * comme joker dans le nom du MBean.

Résultat :
[arthas@12844]$ mbean java.lang:type=Class*
 NAME                   VALUE
----------------------------------------------------
 Verbose                false
 LoadedClassCount       3994
 UnloadedClassCount     10
 TotalLoadedClassCount  4004
 ObjectName             java.lang:type=ClassLoading
 
[arthas@12844]$

Il est aussi possible d'utiliser le caractère * comme joker dans le nom de l'attribut.

Résultat :
[arthas@12844]$ mbean java.lang:type=ClassLoading *Count
 NAME                   VALUE
------------------------------
 LoadedClassCount       3970
 UnloadedClassCount     10
 TotalLoadedClassCount  3980


L'option -E permet d'utiliser une expression régulière.

Résultat :
[arthas@12844]$ mbean -E java.lang:type=ClassLoading LoadedClassCount|TotalLoadedClas
sCount
 NAME                   VALUE
------------------------------
 LoadedClassCount       3979
 TotalLoadedClassCount  3989
 
[arthas@12844]$

Il est possible de surveiller un MBean en précisant un intervalle de rafraichissement.

Résultat :
[arthas@12844]$ mbean -i 500 java.lang:type=ClassLoading *Count
 NAME                   VALUE
------------------------------
 LoadedClassCount       3970
 UnloadedClassCount     10
 TotalLoadedClassCount  3980
 
NAME                   VALUE
------------------------------
 LoadedClassCount       3970
 UnloadedClassCount     10
 TotalLoadedClassCount  3980


Il faut utiliser la combinaison de touche Ctrl+C pour arrêter la commande.

 

120.3.3.9. La commande logger

La commande logger permet d'afficher des informations sur les loggers et de modifier leur niveau de gravité.

La syntaxe est de la forme :

logger [-c <value>] [-h] [--include-arthas-logger] [--include-no-appender] [-l <value>] [-n <value>]

La commande logger possède plusieurs paramètres optionnels :

Paramètre

Rôle

-c, --classloader <value>

Préciser le hashcode du ClassLoader concerné. La valeur par défaut est celle du SystemClassLoader

--include-arthas-logger

Tenir compte des loggers d'Arthas. La valeur par défaut est false

--include-no-appender

Tenir compte des loggers qui n'ont pas d'appender. La valeur par défaut est false

-l, --level <value>

Modifier le niveau de gravité du logger

-n, --name <value>

Préciser le nom du logger concerné


Sans option, la commande logger affiche tous les loggers avec leur appenders associés.

Résultat :
[arthas@4736]$ logger
 name              ROOT
 class             ch.qos.logback.classic.Logger
 classLoader       sun.misc.Launcher$AppClassLoader@73d16e93
 classLoaderHash   73d16e93
 level             WARN
 effectiveLevel    WARN
 additivity        true
 codeSource        file:/C:/Users/jm/.m2/repository/ch/qos/logback/logback-classic/1.2
                   .3/logback-classic-1.2.
                   3.jar
 appenders         name            STDOUT
                   class           ch.qos.logback.core.ConsoleAppender
                   classLoader     sun.misc.Launcher$AppClassLoader@73d16e93
                   classLoaderHash 73d16e93
                   target          System.out
                   name            APPLICATION
                   class           ch.qos.logback.core.rolling.RollingFileAppender
                   classLoader     sun.misc.Launcher$AppClassLoader@73d16e93
                   classLoaderHash 73d16e93
                   file            app.log
                   name            ASYNC
                   class           ch.qos.logback.classic.AsyncAppender
                   classLoader     sun.misc.Launcher$AppClassLoader@73d16e93
                   classLoaderHash 73d16e93
                   blocking        true
                   appenderRef     [APPLICATION]
 
 name              fr.jmdoudoux.dej
 class             ch.qos.logback.classic.Logger
 classLoader       sun.misc.Launcher$AppClassLoader@73d16e93
 classLoaderHash   73d16e93
 level             INFO
 effectiveLevel    INFO
 additivity        false
 codeSource        file:/C:/Users/jm/.m2/repository/ch/qos/logback/logback-classic/1.2
                   .3/logback-classic-1.2.3.jar
 appenders         name            STDOUT
                   class           ch.qos.logback.core.ConsoleAppender
                   classLoader     sun.misc.Launcher$AppClassLoader@73d16e93
                   classLoaderHash 73d16e93
                   target          System.out
 
[arthas@4736]$

L'option -n permet de préciser le nom d'un logger particulier.

Résultat :
[arthas@4736]$ logger -n fr.jmdoudoux
 name              fr.jmdoudoux
 class             ch.qos.logback.classic.Logger
 classLoader       sun.misc.Launcher$AppClassLoader@73d16e93
 classLoaderHash   73d16e93
 level             null
 effectiveLevel    WARN
 additivity        true
 codeSource        file:/C:/Users/jm/.m2/repository/ch/qos/logback/logback-classic/1.
                   2.3/logback-classic-1.2.3.jar
 
[arthas@4736]$ logger -n fr.jmdoudoux.dej
 name              fr.jmdoudoux.dej
 class             ch.qos.logback.classic.Logger
 classLoader       sun.misc.Launcher$AppClassLoader@73d16e93
 classLoaderHash   73d16e93
 level             INFO
 effectiveLevel    INFO
 additivity        false
 codeSource        file:/C:/Users/jm/.m2/repository/ch/qos/logback/logback-classic/1.
                   2.3/logback-classic-1.2.3.jar
 appenders         name            STDOUT
                   class           ch.qos.logback.core.ConsoleAppender
                   classLoader     sun.misc.Launcher$AppClassLoader@73d16e93
                   classLoaderHash 73d16e93
                   target          System.out
 
[arthas@4736]$

L'option -l permet de modifier le niveau de gravité du logger en précisant la nouvelle valeur en paramètre.

Résultat :
[arthas@4736]$ logger -n fr.jmdoudoux.dej -l DEBUG
update logger level success.
[arthas@4736]$ logger -n fr.jmdoudoux.dej | grep level
 level             DEBUG
[arthas@4736]$

 

120.3.4. Les fonctionnalités concernant les classes/classloaders

Arthas propose plusieurs fonctionnalités concernant les classes ou les classloaders :

Commande

Rôle

sc

Chercher des classes parmi celles chargées dans la JVM

sm

Chercher des méthodes dans les classes chargées

jad

Décompiler le bytecode d'une class chargée

mc

Compiler en mémoire un fichier .java pour générer le bytecode dans la JVM

redefine

Charger un fichier .class et remplacer celui existant dans la JVM

dump

Extraire le bytecode chargé dans un fichier

classloader

Afficher des informations relatives aux ClassLoaders et interagir avec eux

getstatic

Afficher la valeur d'une propriété statique

ognl

Exécuter une expression au format ognl

 

120.3.4.1. La commande getstatic

La commande getstatic permet d'afficher la valeur d'un champ static.

La syntaxe est :

getstatic [-c <value>] [-x <value>] [-h] [-E] class-pattern field-pattern [express]

La commande getstatic possède plusieurs paramètres :

Paramètre

Rôle

-c, --classloader <value>

Préciser le hashcode du classloader concerné

-E, --regex

Activer l'utilisation d'une expression régulière. Par défaut, seul le caractère * est utilisable

<class-pattern>

Motif pour le nom de la classe. Le séparateur peut être '.' ou '/'

<field-pattern>

Motif pour le nom du champ

<express>

Préciser l'élément à afficher en utilisant la syntaxe OGNL


La façon la plus simple d'utiliser la commande getstatic est de lui passer en paramètre le nom pleinement qualifié de la classe et le nom du champ static concerné.

Résultat :
[arthas@6672]$ getstatic fr.jmdoudoux.dej.Main valeur
field: valeur
@Integer[1234]
Affect(row-cnt:1) cost in 12 ms.
[arthas@6672]$

 

120.3.4.2. La commande dump

La commande dump permet d'extraire le bytecode d'une classe chargée dans la JVM dans un fichier .class.

La syntaxe de la commande dump est de la forme :

dump [-c <value>] [-d <value>] [-h] [-l <value>] [-E <value>] class-pattern

La command dump possède plusieurs options :

Paramètre

Rôle

class-pattern

Motif pour le nom de la classe

[c:]

Préciser le hashcode du classloader utilisé pour charger la classe

[E]

Activer l'utilisation d'expression régulière


Résultat :
[arthas@4192]$ dump fr.jmdoudoux.dej.Compteur
 HASHCODE  CLASSLOADER                                    LOCATION
 55f96302  +-sun.misc.Launcher$AppClassLoader@55f96302    C:\Users\jm\logs\arthas\cla
                                                          ssdump\sun.misc.Launcher
             +-sun.misc.Launcher$ExtClassLoader@54e948e9  $AppClassLoader-55f96302\fr
                                                          \test\Compteur.class
Affect(row-cnt:1) cost in 16 ms.
[arthas@4192]$

 

120.3.4.3. La commande sc

La commande sc (search class) permet de rechercher des classes chargées dans la JVM.

La syntaxe est de la forme :

sc [-c <value>] [-d] [-x <value>] [-f] [-h] [-E] class-pattern

La commande sc possède plusieurs paramètres :

Paramètre

Rôle

class-pattern

Motif du nom pleinement qualifié de classe. Il est possible d'utiliser le séparateur '.' ou '/' ce qui permet de faire un copier/coller du nom d'une classe depuis la stacktrace d'une exception

-c, --classloader <value>

Préciser le hashcode du ClassLoader qui a chargé la classe

-d, --details

Afficher des informations sur la classe

-f, --field

Afficher les champs de la classe. Doit être utilisée avec l'option -d

-h, --help

Afficher l'aide de la commande

-E, --regex

Activer l'utilisation d'une expression régulière dans le motif du nom de classe (par défaut uniquement le caractère *)


Il est possible d'utiliser le caractère * comme joker.

Résultat :
[arthas@9840]$ sc fr.jmdoudoux.dej.*
fr.jmdoudoux.dej.Compteur
fr.jmdoudoux.dej.Main
fr.jmdoudoux.dej.Main$1
fr.jmdoudoux.dej.Service
fr.jmdoudoux.dej.ThreadService
Affect(row-cnt:5) cost in 3 ms.
[arthas@9840]$

Il est donc aussi possible de demander la liste de toutes les classes chargées dans la JVM : attention la liste peut être importante.

Résultat :
[arthas@9840]$ sc * | grep fr.test
fr.jmdoudoux.dej.Compteur
fr.jmdoudoux.dej.Main
fr.jmdoudoux.dej.Main$1
fr.jmdoudoux.dej.Service
fr.jmdoudoux.dej.ThreadService
[arthas@9840]$

L'option -d permet d'afficher des informations sur une classe

Résultat :
[arthas@9840]$ sc -d fr.jmdoudoux.dej.Compteur
 class-info        fr.jmdoudoux.dej.Compteur
 code-source       /C:/java/arthas-demo.jar
 name              fr.jmdoudoux.dej.Compteur
 isInterface       false
 isAnnotation      false
 isEnum            false
 isAnonymousClass  false
 isArray           false
 isLocalClass      false
 isMemberClass     false
 isPrimitive       false
 isSynthetic       false
 simple-name       Compteur
 modifier          public
 annotation
 interfaces
 super-class       +-java.lang.Object
 class-loader      +-sun.misc.Launcher$AppClassLoader@55f96302
                     +-sun.misc.Launcher$ExtClassLoader@49487aa8
 classLoaderHash   55f96302
 
Affect(row-cnt:1) cost in 8 ms.

L'option -f combinée avec l'option -d permet d'afficher dans le détail des informations sur la classe et ses champs.

Résultat :
[arthas@9840]$ sc -df fr.jmdoudoux.dej.Compteur
 class-info        fr.jmdoudoux.dej.Compteur
 code-source       /C:/java/workspace-2018-12-Test/Arthas-demo/arthas-demo.jar
 name              fr.jmdoudoux.dej.Compteur
 isInterface       false
 isAnnotation      false
 isEnum            false
 isAnonymousClass  false
 isArray           false
 isLocalClass      false
 isMemberClass     false
 isPrimitive       false
 isSynthetic       false
 simple-name       Compteur
 modifier          public
 annotation
 interfaces
 super-class       +-java.lang.Object
 class-loader      +-sun.misc.Launcher$AppClassLoader@55f96302
                     +-sun.misc.Launcher$ExtClassLoader@49487aa8
 classLoaderHash   55f96302
 fields            name     valeur
                   type     java.util.concurrent.atomic.AtomicInteger
                   modifier private,static
                   value    601
 
 
Affect(row-cnt:1) cost in 6 ms.

 

120.3.4.4. La commande sm

La commande sm (search method) permet de rechercher les méthodes d'une classe chargée dans la JVM. Seules les méthodes déclarées dans la classe sont trouvées : les méthodes héritées ne sont pas affichées.

La syntaxe est de la forme :

sm [-c <value>] [-d] [-h] [-E] class-pattern [method-pattern]

La commande sm possède plusieurs paramètres :

Paramètre

Rôle

class-pattern

Motif du nom pleinement qualifié de classe. Il est possible d'utiliser le séparateur '.' ou '/' ce qui permet de faire un copier/coller du nom d'une classe depuis la stacktrace d'une exception

method-pattern

Motif du nom de la méthode

-c, --classloader <value>

Préciser le hashcode du ClassLoader qui a chargé la classe

-d, --details

Affiche le détail de la méthode

-E, --regex

Activer l'utilisation d'une expression régulière dans le motif du nom de classe (par défaut uniquement le caractère *)


En passant uniquement le motif du nom de classe, la commande sm affiche les méthodes de la classe.

Résultat :
[arthas@4192]$ sm fr.jmdoudoux.dej.Compteur
fr.jmdoudoux.dej.Compteur <init>()V
fr.jmdoudoux.dej.Compteur incrementer()I
Affect(row-cnt:2) cost in 2 ms.
[arthas@4192]$

L'option -d permet d'afficher des détails sur la méthode fournie en paramètre.

Résultat :
[arthas@4192]$ sm -d fr.jmdoudoux.dej.Compteur incrementer
 declaring-class  fr.jmdoudoux.dej.Compteur
 method-name      incrementer
 modifier         public
 annotation
 parameters
 return           int
 exceptions
 classLoaderHash  55f96302
 
Affect(row-cnt:1) cost in 3 ms.
[arthas@4192]$

 

120.3.4.5. La commande classloader

La commande classloader permet d'interagir avec les classloaders utilisés dans la JVM

La syntaxe est de la forme :

classloader [-a] [-c <value>] [-h] [-i] [-l] [--load <value>] [-r <value>] [-t]

La commande classloader possède plusieurs paramètres :

Paramètre

Rôle

-a, --all

Afficher les classes chargées

-c, --classloader <value>

Préciser le hashcode du ClassLoader concerné

-i, --include-reflection-classloader

Inclure aussi sun.reflect.DelegatingClassLoader

-l, --list-classloader

Afficher pour chaque ClassLoader des informations (nombre de classes chargées, valeur de hachage, ClassLoader parent)

--load <value>

Charger une classe par le ClassLoader précisé avec l'option -c

-r, --resource <value>

Rechercher une ressource en utilisant le ClassLoader précisé avec l'option -c

-t, --tree

Afficher la hiérarchie des ClassLoaders


Sans option, la commande classloader affiche pour chaque classloader le nombre d'instances et le nombre de classes chargées.

Résultat :
[arthas@9840]$ classloader
 name                                       numberOfInstances  loadedCountTotal
 BootstrapClassLoader                       1                  1591
 com.taobao.arthas.agent.ArthasClassloader  1                  1107
 sun.misc.Launcher$AppClassLoader           1                  8
 sun.reflect.DelegatingClassLoader          6                  6
 sun.misc.Launcher$ExtClassLoader           1                  5
Affect(row-cnt:5) cost in 2 ms.
[arthas@9840]$

L'option -l affiche des informations sur chaque ClassLoader.

Résultat :
[arthas@9840]$ classloader -l
      
 name                            loadedCount  hash      parent
 BootstrapClassLoader            1591         null      null
 com.taobao.arthas.agent.Arthas  1108         2822a77f  sun.misc.Launcher$ExtClassLoa
 Classloader@2822a77f                                   der@49487aa8
 sun.misc.Launcher$AppClassLoad  8            55f96302  sun.misc.Launcher$ExtClassLoa
 er@55f96302                                            der@49487aa8
 sun.misc.Launcher$ExtClassLoad  5            49487aa8  null
 er@49487aa8
Affect(row-cnt:4) cost in 5 ms.
[arthas@9840]$

L'option -t affiche la hiérarchie des classloaders.

Résultat :
[arthas@9840]$ classloader -t
+-BootstrapClassLoader
+-sun.misc.Launcher$ExtClassLoader@49487aa8
  +-com.taobao.arthas.agent.ArthasClassloader@2822a77f
  +-sun.misc.Launcher$AppClassLoader@55f96302
Affect(row-cnt:4) cost in 2 ms.
[arthas@9840]$

L'option -c affiche les URL de l'URLClassLoader

Résultat :
[arthas@9840]$ classloader -c 55f96302
file:/C:/java/workspace-2018-12-Test/Arthas-demo/arthas-demo.jar
file:/C:/Users/jm/.arthas/lib/3.1.7/arthas/arthas-agent.jar
 
Affect(row-cnt:8) cost in 4 ms. 
[arthas@9840]$

L'option -r permet de rechercher une ressource par le ClassLoader.

Résultat :
[arthas@9840]$ classloader -c 55f96302 -r maconfig.properties
 jar:file:/C:/java/workspace/Arthas-demo/arthas-demo.jar!/maconfig.properties
 
Affect(row-cnt:1) cost in 2 ms. 
[arthas@9840]$

L'option --load permet de charger une classe par le Classloader

Résultat :
[arthas@9840]$ classloader -c 55f96302 --load fr.jmdoudoux.dej.AutreClasse
load class success.
 class-info        fr.jmdoudoux.dej.AutreClasse
 code-source       /C:/java/workspace/Arthas-demo/arthas-demo.jar
 name              fr.jmdoudoux.dej.AutreClasse
 isInterface       false
 isAnnotation      false
 isEnum            false
 isAnonymousClass  false
 isArray           false
 isLocalClass      false
 isMemberClass     false
 isPrimitive       false
 isSynthetic       false
 simple-name       AutreClasse
 modifier          public
 annotation
 interfaces
 super-class       +-java.lang.Object
 class-loader      +-sun.misc.Launcher$AppClassLoader@55f96302
                     +-sun.misc.Launcher$ExtClassLoader@1ac18008
 classLoaderHash   55f96302 
[arthas@9840]$

L'option -a permet d'afficher les classes chargées. Attention, le nombre de classes chargées peut être important. Il est possible de ne demander que les classes chargées par un Classloader particulier en utilisant en complément l'option -c.

Résultat :
[arthas@9840]$ classloader -c 55f96302 -a
 hash:1442407170, sun.misc.Launcher$AppClassLoader@55f96302
 com.taobao.arthas.agent.AgentBootstrap
 com.taobao.arthas.agent.AgentBootstrap$1
 com.taobao.arthas.agent.ArthasClassloader
 fr.jmdoudoux.dej.AbstractCompteur
 fr.jmdoudoux.dej.AutreClasse
 fr.jmdoudoux.dej.Compteur
 fr.jmdoudoux.dej.Main
 fr.jmdoudoux.dej.Main$1
 fr.jmdoudoux.dej.Service
 fr.jmdoudoux.dej.ThreadService
 
Affect(row-cnt:0) cost in 12 ms.
 
[arthas@9840]$

 

120.3.4.6. La commande jad

La commande jad permet de décompiler une classe. Le code décompilé est mis en évidence par une coloration syntaxique pour une meilleure lisibilité dans la console.

La décompilation peut être intéressante et utile pour vérifier que c'est la bonne version d'une classe qui est utilisée ou pour pouvoir la modifier avant de la recompiler et de la recharger à chaud.

La syntaxe de la commande est de la forme :

jad [-c <value>] [-h] [-E] [--source-only] class-pattern [method-name]

La commande jad possède plusieurs paramètres :

Paramètre

Rôle

-c <value>

Préciser le hashcode du ClassLoader qui a chargé la classe

-E, --regex

Activer l'utilisation d'une expression régulière dans le motif du nom de classe (par défaut uniquement le caractère *)

--source-only

Obtenir uniquement le code source décompilé

<class-pattern>

Motif du nom pleinement qualifié de classe. Il est possible d'utiliser le séparateur '.' ou '/'

<method-name>

Motif de la méthode de la classe à uniquement décompilée


Pour décompiler une classe, il suffit de préciser son nom pleinement qualifié comme paramètre.

Résultat :
[arthas@9840]$ jad fr.jmdoudoux.dej.Compteur
 
ClassLoader:
+-sun.misc.Launcher$AppClassLoader@55f96302
  +-sun.misc.Launcher$ExtClassLoader@49487aa8
 
Location:
/C:/java/workspace/Arthas-demo/arthas-demo.jar
 
/*
 * Decompiled with CFR.
 */
package fr.test;
 
import java.util.concurrent.atomic.AtomicInteger;
 
public class Compteur {
    private static AtomicInteger valeur = new AtomicInteger(0);
 
    public int incrementer() {
        return valeur.incrementAndGet();
    }
}
 
Affect(row-cnt:1) cost in 753 ms.
[arthas@9840]$

Par défaut, le commande affiche des informations sur le classloader et l'artefact qui contient la classe. Pour n'afficher que le code source issue de la décompilation, il faut utiliser l'option --source-only.

Résultat :
[arthas@9840]$ jad --source-only fr.jmdoudoux.dej.Compteur
/*
 * Decompiled with CFR.
 */
package fr.test;
 
import java.util.concurrent.atomic.AtomicInteger;
 
public class Compteur {
    private static AtomicInteger valeur = new AtomicInteger(0);
 
    public int incrementer() {
        return valeur.incrementAndGet();
    }
}
 
[arthas@9840]$

Il est possible de rediriger la sortie de la commande dans un fichier.

Résultat :
[arthas@9840]$ jad --source-only fr.jmdoudoux.dej.Compteur > c:/temp/Compteur.java 
[arthas@9840]$

Il est possible de ne demander que de décompiler une méthode d'une classe en les précisant en paramètres.

Résultat :
[arthas@9840]$ jad fr.jmdoudoux.dej.Compteur incrementer
 
ClassLoader:
+-sun.misc.Launcher$AppClassLoader@55f96302
  +-sun.misc.Launcher$ExtClassLoader@1ac18008
 
Location:
/C:/java/workspace-2018-12-Test/Arthas-demo/arthas-demo.jar
 
public int incrementer() {
    return valeur.incrementAndGet();
}
 
Affect(row-cnt:1) cost in 107 ms.
[arthas@9840]$

Si la classe à décompiler est chargée plusieurs fois, il faut préciser le ClassLoader concerné avec l'option -c.

 

120.3.4.7. La commande mc

La commande mc utilise un compilateur en mémoire pour compiler des fichiers code source Java en fichiers .class contenant du bytecode.

La syntaxe de la commande est de la forme :

mc [-c <value>] [-d <value>] [--encoding <value>] [-h] sourcefiles...

La commande mc possède plusieurs paramètres :

Paramètre

Rôle

-c, --classloader <value>

Préciser le hashcode du ClassLoader a utilisé

-d, --directory <value>

Préciser le répertoire dans lequel le résultat de la compilation va être stocké

--encoding <value>

Le jeu de caractères utilisé pour l'encodage du code source

<sourcefiles>

Le ou les fichiers source


L'option -d permet de préciser le répertoire qui va contenir le résultat de la compilation.

Résultat :
[arthas@9840]$ cat c:/temp/Compteur.java
/*
 * Decompiled with CFR.
 */
package fr.test;
 
import java.util.concurrent.atomic.AtomicInteger;
 
public class Compteur {
    private static AtomicInteger valeur = new AtomicInteger(0);
 
    public int incrementer() {
        System.out.println("incrementer");
        return valeur.incrementAndGet();
    }
}
 
[arthas@9840]$ mc -d c:/temp c:/temp/Compteur.java
Memory compiler output:
c:\temp\fr\test\Compteur.class
Affect(row-cnt:1) cost in 62 ms.
[arthas@9840]$

 

120.3.4.8. La commande redefine

La commande redefine permet de recharger à chaud une classe.

La syntaxe de la commande est de la forme :

redefine [-c <value>] [-h] classfilePaths...

La commande redefine possède plusieurs paramètres dont :

Paramètre

Rôle

-c, --classloader <value>

Préciser le hashcode du ClassLoader à utiliser


Avant de pouvoir recharger une classe, il faut trouver le hashcode de son ClassLoader pour le réutiliser pour le rechargement.

Résultat :
[arthas@9840]$ sc -d fr.jmdoudoux.dej.Compteur
 class-info        fr.jmdoudoux.dej.Compteur
 code-source       /C:/java/workspace-2018-12-Test/Arthas-demo/arthas-demo.jar
 name              fr.jmdoudoux.dej.Compteur
 isInterface       false
 isAnnotation      false
 isEnum            false
 isAnonymousClass  false
 isArray           false
 isLocalClass      false
 isMemberClass     false
 isPrimitive       false
 isSynthetic       false
 simple-name       Compteur
 modifier          public
 annotation
 interfaces
 super-class       +-java.lang.Object
 class-loader      +-sun.misc.Launcher$AppClassLoader@55f96302
                   +-sun.misc.Launcher$ExtClassLoader@49487aa8
 classLoaderHash   55f96302
 
Affect(row-cnt:1) cost in 11 ms.

[arthas@9840]$ redefine -c 55f96302 c:/temp/fr/test/Compteur.class
redefine success, size: 1
[arthas@9840]$

La commande redefine utilise la méthode redefineClasses() de la classe Instrumentation : elle suit donc les restrictions induites par l'utilisation de cette méthode. Il n'est par exemple pas possible d'ajouter, supprimer ou renommer un membre de la classe, de changer la signature d'une méthode ni de changer l'héritage de la classe.

Une fois la classe rechargée, elle ne peut pas être restaurée même en après l'invocation de la commande reset : la seule solution est de recharger la version initiale préalablement sauvegardée.

La commande redefine entre en conflit avec les commandes jad, monitor, trace, tt et watch. Après l'exécution de la commande redefine, si vous exécutez une des commandes précédentes, le bytecode de la classe sera réinitialisé.

 

120.3.4.9. La commande ognl

Le commande ognl permet d'évaluer une expression OGNL (Object Graph Navigation Language) et d'afficher le résultat de cette évaluation.

La syntaxe de la commande est de la forme :

ognl [-c <value>] [-x <value>] [-h] express

La commande ognl possède plusieurs paramètres :

Paramètre

Rôle

-c, --classloader <value>

Préciser le hashcode du ClassLoader à utiliser

-x, --expand <value>

Niveau de profondeur lors du parcours des objets (la valeur par défaut est 1)

Express

Expression ognl à évaluer


Le guide de la syntaxe des expressions est consultable à l'url :
https://commons.apache.org/proper/commons-ognl/language-guide.html

Par exemple, l'expression peut demander la valeur d'une propriété statique :

Résultat :
[arthas@11140]$  ognl '@fr.jmdoudoux.dej.Compteur@valeur'
@AtomicInteger[
    serialVersionUID=@Long[6214790243416807050],
    unsafe=@Unsafe[sun.misc.Unsafe@1b417cbd],
    valueOffset=@Long[12],
    value=@Integer[18047],
    serialVersionUID=@Long[-8742448824652078965],
]
[arthas@11140]$

L'expression peut invoquer une méthode statique

Résultat :
 [arthas@11140]$ ognl '@fr.jmdoudoux.dej.Service@fabriquer("test",5)'
@AutreClasse[
    dateCrea=@LocalDateTime[2020-03-08T22:02:19.518],
    nom=@String[test],
    taille=@Integer[5],
]
[arthas@11140]$

L'expression peut contenir plusieurs valeurs.

Résultat :
[arthas@11140]$ ognl '#valeur1=@System@getProperty("user.home"), #valeur2=
@System@getProperty("java.version"),  {#valeur1, #valeur2}'
@ArrayList[
    @String[C:\Users\jm],
    @String[1.8.0_202],
]
[arthas@11140]$

 

120.3.5. Les fonctionnalités de profiling

Arthas propose plusieurs commandes relatives à la JVM :

Commande

Rôle

monitor

Surveiller les invocations de méthodes pour afficher des statistiques sur leurs exécutions

watch

Afficher des informations sur l'invocation de méthodes : les paramètres, la valeur de retour et les exceptions levées

trace

Tracer le temps d'exécution des méthodes invoquées en premier niveau lors de l'invocation des méthodes suivies

tt

Enregistrer les invocations de méthodes pour permettre leur analyse après la fin de l'enregistrement

stack

Afficher périodiquement la stacktrace d'invocation de méthodes

profiler

Utiliser async-profiler pour obtenir des informations de profiling


Plusieurs commandes (monitor, watch, trace, tt, ...) instrumentent le code en ajoutant du bytecode. Lorsque cette instrumentation n'est plus utile, il est important d'invoquer la commande stop ou reset pour retirer les aspects surtout si la JVM n'est pas arrêtée.

 

120.3.5.1. La commande monitor

La commande monitor permet de surveiller les invocations de méthodes pour afficher des statistiques sur leurs exécutions.

La syntaxe de la commande est de la forme

monitor [-c <value>] [-h] [-n <value>] [-E <value>] class-pattern method-pattern

La commande monitor possède plusieurs paramètres dont :

Options

Rôle

<class-pattern>

Motif pour désigner la ou les classes concernées

<method-pattern>

Motif pour désigner la ou les méthodes concernées

-c ou -cycle

Intervalle d'affichage des informations. La valeur par défaut est 60 secondes

-n ou -limits

Limite d'exécutions

-E ou -regex

Expression régulière


Il faut indiquer le motif de classe et de méthode : par exemple pour une méthode en particulier, il faut préciser le nom pleinement qualifié de la classe et le nom de la méthode.

Résultat :
[arthas@9840]$ monitor fr.jmdoudoux.dej.Service traiter
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 24 ms.
 timestamp            class           method  total success fail avg-rt(ms) fail-rate
-------------------------------------------------------------------------------------
 2020-02-15 23:16:22  fr.jmdoudoux.dej.Service traiter 56    56    0    2075,60    0,00%
[arthas@9840]$

Les informations affichées sont :

Si les motifs fournis ne permettent pas de correspondre à au moins une méthode, alors Arthas affiche un message

Résultat :
[arthas@9840]$ monitor fr.jmdoudoux.dej.Service afficher
No class or method is affected, try:
1. sm CLASS_NAME METHOD_NAME to make sure the method you are tracing actually exists 
(it might be in your parent class).
2. reset CLASS_NAME and try again, your method body might be too large.
3. check arthas log: C:\Users\jm\logs\arthas\arthas.log
4. visit https://github.com/alibaba/arthas/issues/47 for more details.
[arthas@9840]$

Il est aussi possible d'utiliser le caractère joker * dans le motif pour désigner plusieurs classes et/ou méthodes.

Résultat :
[arthas@9840]$ monitor fr.jmdoudoux.dej.* *
Press Q or Ctrl+C to abort.
Affect(class-cnt:7 , method-cnt:13) cost in 94 ms.
 timestamp           class            method      total success fail avg-rt(ms) fail-rate
-----------------------------------------------------------------------------------------
 2020-02-15 23:10:27 fr.jmdoudoux.dej.Compteur incrementer 60    60    0    0,02       0,00%
 2020-02-15 23:10:27 fr.jmdoudoux.dej.Service  traiter     58    58    0    1886,19    0,00%
 
 timestamp           class            method      total success fail avg-rt(ms) fail-rate
-----------------------------------------------------------------------------------------
 2020-02-15 23:11:27 fr.jmdoudoux.dej.Compteur incrementer 67    67    0    0,02       0,00%
 2020-02-15 23:11:27 fr.jmdoudoux.dej.Service  traiter     67    67    0    1774,72    0,00%
[arthas@9840]$

L'option -c permet de préciser le nombre de secondes à attendre avant que la commande n'affiche des statistiques.

Résultat :
[arthas@9840]$ monitor fr.jmdoudoux.dej.Service traiter -c 5
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 48 ms.
 timestamp            class            method   total  success  fail  avg-rt(ms)  fail-rate
--------------------------------------------------------------------------------------------
 2020-01-19 21:32:01  fr.jmdoudoux.dej.Service  traiter  2      2     0     2041,27     0,00%
 
 timestamp            class            method   total  success  fail  avg-rt(ms)  fail-rate
--------------------------------------------------------------------------------------------
 2020-01-19 21:32:06  fr.jmdoudoux.dej.Service  traiter  0      0     0     0,00        0,00%
 
 timestamp            class            method   total  success  fail  avg-rt(ms)  fail-rate
--------------------------------------------------------------------------------------------
 2020-01-19 21:32:11  fr.jmdoudoux.dej.Service  traiter  2      2     0     1539,91     0,00%
 
 timestamp            class            method   total  success  fail  avg-rt(ms)  fail-rate
--------------------------------------------------------------------------------------------
 2020-01-19 21:32:16  fr.jmdoudoux.dej.Service  traiter  1      1     0     2042,88     0,00%
 
 timestamp            class            method   total  success  fail  avg-rt(ms)  fail-rate
--------------------------------------------------------------------------------------------
 2020-01-19 21:32:21  fr.jmdoudoux.dej.Service  traiter  1      1     0     4037,81     0,00%
 
 timestamp            class            method   total  success  fail  avg-rt(ms)  fail-rate
--------------------------------------------------------------------------------------------
 2020-01-19 21:32:26  fr.jmdoudoux.dej.Service  traiter  3      3     0     3044,34     0,00%
 
[arthas@9840]$

La commande monitor ne rend pas la main immédiatement. Pour arrêter l'exécution de la méthode, il faut utiliser la combinaison de touche Ctrl+C.

L'option -n permet de préciser le nombre d'itérations à atteindre avant d'arrêter l'exécution de la commande.

Résultat :
[arthas@9840]$ monitor fr.jmdoudoux.dej.Service * -c 5 -n 3
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:2) cost in 27 ms.
 timestamp            class            method   total  success  fail  avg-rt(ms)  fail-rate
--------------------------------------------------------------------------------------------
 2020-02-15 23:25:37  fr.jmdoudoux.dej.Service  traiter  1      1     0     2054,73     0,00%
 
 timestamp            class            method   total  success  fail  avg-rt(ms)  fail-rate
--------------------------------------------------------------------------------------------
 2020-02-15 23:25:42  fr.jmdoudoux.dej.Service  traiter  4      4     0     2542,40     0,00%
 
 timestamp            class            method   total  success  fail  avg-rt(ms)  fail-rate
--------------------------------------------------------------------------------------------
 2020-02-15 23:25:47  fr.jmdoudoux.dej.Service  traiter  6      6     0     1545,81     0,00%
 
Command execution times exceed limit: 3, so command will exit. You can set it with -n option.
[arthas@9840]$

Du côté du serveur d'Arthas, la commande s'exécute en arrière-plan, mais le code tissé n'a plus d'effet une fois la commande terminée.

 

120.3.5.2. La commande stack

La commande stack permet d'afficher périodiquement la stacktrace d'invocation de méthodes. Cela permet de savoir qui appelle la ou les méthodes sélectionnées.

La syntaxe de la commande stack est de la forme :

stack [-h] [-n <value>] [-E] class-pattern [method-pattern] [condition-express]

La commande stack possède plusieurs paramètres dont :

Options

Rôle

<class-pattern>

Motif pour désigner la ou les classes concernées

<method-pattern>

Motif pour désigner la ou les méthodes concernées

<condition-express>

Expression conditionnelle au format ognl

-n, --limits <value>

Limite d'exécution

-E, --regex

Expression régulière


Il faut au moins préciser la ou les classes concernées : dans ce cas toutes leurs méthodes sont prises en comptes.

Résultat :
[arthas@9840]$ stack fr.jmdoudoux.dej.Compteur
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:2) cost in 80 ms.
ts=2020-01-19 23:50:13;thread_name=Service_1;id=a;is_daemon=false;priority=5;TCCL=sun
    .misc.Launcher$AppClassLoader@55f96302
    @fr.jmdoudoux.dej.Service.traiter()
        at fr.jmdoudoux.dej.ThreadService.run(ThreadService.java:18)
 
ts=2020-01-19 23:50:18;thread_name=Service_1;id=a;is_daemon=false;priority=5;TCCL=sun
    .misc.Launcher$AppClassLoader@55f96302
    @fr.jmdoudoux.dej.Service.traiter()
        at fr.jmdoudoux.dej.ThreadService.run(ThreadService.java:18)
 
 [arthas@9840]$

Il est possible de préciser uniquement une seule méthode en paramètre pour restreindre les informations à cette dernière.

Résultat :
[arthas@9840]$ stack fr.jmdoudoux.dej.Compteur incrementer
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 20 ms.
ts=2020-01-19 23:52:15;thread_name=Service_1;id=a;is_daemon=false;priority=5;TCCL=sun
    .misc.Launcher$AppClassLoader@55f96302
    @fr.jmdoudoux.dej.Service.traiter()
        at fr.jmdoudoux.dej.ThreadService.run(ThreadService.java:18)
 
ts=2020-01-19 23:52:20;thread_name=Service_1;id=a;is_daemon=false;priority=5;TCCL=sun
    .misc.Launcher$AppClassLoader@55f96302
    @fr.jmdoudoux.dej.Service.traiter()
        at fr.jmdoudoux.dej.ThreadService.run(ThreadService.java:18)
 
ts=2020-01-19 23:52:20;thread_name=Service_2;id=b;is_daemon=false;priority=5;TCCL=sun
    .misc.Launcher$AppClassLoader@55f96302
    @fr.jmdoudoux.dej.Service.traiter()
        at fr.jmdoudoux.dej.ThreadService.run(ThreadService.java:18)
 
[arthas@9840]$

La commande s'exécute tant qu'elle n'est pas interrompue avec la combinaison de touches Ctrl + C.

L'option -n permet de préciser un nombre maximum d'invocations avant que la commande s'interrompe.

Résultat :
[arthas@9840]$ stack fr.jmdoudoux.dej.Compteur incrementer -n 3
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 12 ms.
ts=2020-02-20 20:12:53;thread_name=Service_2;id=b;is_daemon=false;priority=5;TCCL=sun
    .misc.Launcher$AppClassLoader@55f96302
    @fr.jmdoudoux.dej.Service.traiter()
        at fr.jmdoudoux.dej.ThreadService.run(ThreadService.java:18)
 
ts=2020-02-20 20:12:55;thread_name=Service_1;id=a;is_daemon=false;priority=5;TCCL=sun
    .misc.Launcher$AppClassLoader@55f96302
    @fr.jmdoudoux.dej.Service.traiter()
        at fr.jmdoudoux.dej.ThreadService.run(ThreadService.java:18)
 
ts=2020-02-20 20:12:56;thread_name=Service_2;id=b;is_daemon=false;priority=5;TCCL=sun
    .misc.Launcher$AppClassLoader@55f96302
    @fr.jmdoudoux.dej.Service.traiter()
        at fr.jmdoudoux.dej.ThreadService.run(ThreadService.java:18)
 
Command execution times exceed limit: 3, so command will exit. You can set it with -n
 option. 
[arthas@9840]$

Le nombre d'invocations d'une méthode peut être important : il est possible d'utiliser une expression ognl pour conditionner les informations affichées.

Résultat :
[arthas@9840]$ stack fr.jmdoudoux.dej.* * '#cost>100' -n 2
Press Q or Ctrl+C to abort.
Affect(class-cnt:7 , method-cnt:13) cost in 98 ms.
ts=2020-02-16 22:43:25;thread_name=Service_2;id=b;is_daemon=false;priority=5;TCCL=sun
    .misc.Launcher$AppClassLoader@55f96302
    @fr.jmdoudoux.dej.Service.traiter()
        at fr.jmdoudoux.dej.ThreadService.run(ThreadService.java:-1)
 
ts=2020-02-16 22:43:26;thread_name=Service_2;id=b;is_daemon=false;priority=5;TCCL=sun
    .misc.Launcher$AppClassLoader@55f96302
    @fr.jmdoudoux.dej.Service.traiter()
        at fr.jmdoudoux.dej.ThreadService.run(ThreadService.java:-1)
 
Command execution times exceed limit: 2, so command will exit. You can set it with -n
 option.
[arthas@9840]$

 

120.3.5.3. La commande trace

La commande trace permet de tracer le temps d'exécution des méthode invoquées en premier niveau lors de l'invocation des méthodes suivies. Cela permet de trouver les goulets d'étranglements lors de l'invocation d'une méthode.

La syntaxe de la commande est de la forme :

trace [-h] [-n <value>] [-p <value>] [-E] [--skipJDKMethod <value>] class-pattern method-pattern [condition-express]

La commande trace possède plusieurs paramètres dont :

Options

Rôle

<class-pattern>

Motif pour désigner la ou les classes concernées

<method-pattern>

Motif pour désigner la ou les méthodes concernées

<condition-express>

Expression conditionnelle au format ognl

-n, --limits <value>

Limite d'exécution de la commande

-E, --regex

Expression régulière

-p, --path <value>

 

--skipJDKMethod <value>

Ignorer les méthodes de classes du JDK. Valeur par défaut : true


Le plus simple est de préciser le motif de la classe et de la méthode concernée

Résultat :
[arthas@9840]$ trace fr.jmdoudoux.dej.Service traiter
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 22 ms.
`---ts=2020-01-19 23:56:54;thread_name=Service_2;id=b;is_daemon=false;priority=5;TCCL=sun
    .misc.Launcher$AppClassLoader@55f96302
    `---[4042.1098ms] fr.jmdoudoux.dej.Service:traiter()
        `---[0.7561ms] fr.jmdoudoux.dej.Compteur:incrementer() #11
 
`---ts=2020-01-19 23:56:57;thread_name=Service_1;id=a;is_daemon=false;priority=5;TCCL=sun
    .misc.Launcher$AppClassLoader@55f96302
    `---[2041.5307ms] fr.jmdoudoux.dej.Service:traiter()
        `---[0.5413ms] fr.jmdoudoux.dej.Compteur:incrementer() #11
 
`---ts=2020-01-19 23:57:00;thread_name=Service_1;id=a;is_daemon=false;priority=5;TCCL=sun
    .misc.Launcher$AppClassLoader@55f96302
    `---[41.7881ms] fr.jmdoudoux.dej.Service:traiter()
        `---[0.6608ms] fr.jmdoudoux.dej.Compteur:incrementer() #11

La première de chaque invocation affiche l'heure, des informations sur le thread et le ClassLoader.

Pour chaque méthode invoquée en premier niveau durant une exécution plusieurs informations sont affichées : le temps d'exécution entre crochets et des informations statistiques si le nombre d'invocations est supérieur à 1.

La commande s'exécute tant qu'elle n'est pas interrompue avec la combinaison de touches Ctrl + C.

L'option -n permet de préciser le nombre d'invocations à afficher avant d'arrêter l'exécution de la commande.

Résultat :
[arthas@9840]$ trace fr.jmdoudoux.dej.Service traiter -n 1
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 17 ms.
`---ts=2020-02-20 20:59:28;thread_name=Service_2;id=b;is_daemon=false;priority=5;TCCL
    =sun.misc.Launcher$AppClassLoader@55f96302
    `---[103.0994ms] fr.jmdoudoux.dej.Service:traiter()
        `---[0.0633ms] fr.jmdoudoux.dej.Compteur:incrementer() #11
 
Command execution times exceed limit: 1, so command will exit. You can set it with -n option.
[arthas@9840]$

Il est possible de préciser une expression ognl pour limiter les invocations restituées. Par exemple, dans l'exemple ci-dessous, seules les invocations qui durent plus de 2 secondes sont affichées.

Résultat :
[arthas@9840]$ trace fr.jmdoudoux.dej.Service traiter '#cost > 2000'
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 31 ms.
`---ts=2020-01-20 00:05:14;thread_name=Service_1;id=a;is_daemon=false;priority=5;TCCL
    =sun.misc.Launcher$AppClassLoader@55f96302
    `---[4048.5473ms] fr.jmdoudoux.dej.Service:traiter()
        `---[0.723ms] fr.jmdoudoux.dej.Compteur:incrementer() #11
 
`---ts=2020-01-20 
00:05:30;thread_name=Service_2;id=b;is_daemon=false;priority=5;TCCL=sun.misc.Launcher
    $AppClassLoader@55f96302
    `---[3037.0302ms] fr.jmdoudoux.dej.Service:traiter()
        `---[0.9308ms] fr.jmdoudoux.dej.Compteur:incrementer() #11
 
`---ts=2020-01-20 00:05:33;thread_name=Service_1;id=a;is_daemon=false;priority=5;TCCL
    =sun.misc.Launcher$AppClassLoader@55f96302
    `---[2035.4533ms] fr.jmdoudoux.dej.Service:traiter()
        `---[0.9851ms] fr.jmdoudoux.dej.Compteur:incrementer() #11
 
[arthas@9840]$

L'option --skipJDKMethod permet de prendre en compte ou non les méthodes de classes du JDK.

Résultat :
[arthas@9840]$ trace --skipJDKMethod false fr.jmdoudoux.dej.Service traiter
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 13 ms.
`---ts=2020-02-20 20:55:17;thread_name=Service_2;id=b;is_daemon=false;priority=5;TCCL
    =sun.misc.Launcher$AppClassLoader@55f96302
    `---[293.1969ms] fr.jmdoudoux.dej.Service:traiter()
        +---[0.1066ms] fr.jmdoudoux.dej.Compteur:incrementer() #11
        +---[0.01ms] java.lang.Math:random() #12
        +---[0.0093ms] java.util.concurrent.TimeUnit:sleep() #12
        `---[min=1.0E-4ms,max=4.0424ms,total=139.8867ms,count=100000] java.util.UUID:
        randomUUID() #15
 
[arthas@9840]$

Il est possible de tracer des méthodes de classes différentes en utilisant une expression régulière en valeur de l'option -E. C'est notamment pratique pour tracer des invocations de niveaux inférieurs.

Résultat :
[arthas@9840]$ trace -E fr.jmdoudoux.dej.Service|fr.jmdoudoux.dej.Compteur traiter|incrementer
Press Q or Ctrl+C to abort.
Affect(class-cnt:2 , method-cnt:2) cost in 50 ms.
`---ts=2020-02-20 21:07:57;thread_name=Service_1;id=a;is_daemon=false;priority=5;TCCL
    =sun.misc.Launcher$AppClassLoader@55f96302
    `---[1104.748ms] fr.jmdoudoux.dej.Service:traiter()
        `---[0.1391ms] fr.jmdoudoux.dej.Compteur:incrementer() #11
            `---[0.0934ms] fr.jmdoudoux.dej.Compteur:incrementer() 
[arthas@9840]$

 

120.3.5.4. La commande watch

La commande watch permet d'afficher des informations sur l'exécution de méthodes : les paramètres, la valeur de retour et les exceptions levées lors d'invocations de méthodes.

La syntaxe de la commande est de la forme :

watch [-b] [-e] [-x <value>] [-f] [-h] [-n <value>] [-E] [-M <value>] [-s] class-pattern method-pattern express [condition-express]

La commande watch possède plusieurs paramètres dont :

Options

Rôle

<class-pattern>

Motif pour désigner la ou les classes concernées. Il est possible d'utiliser le caractère joker *

<method-pattern>

Motif pour désigner la ou les méthodes concernées. Il est possible d'utiliser le caractère joker *

<express>

Les informations à surveiller, en utilisant le format ognl

<condition-express>

Expression conditionnelle au format ognl

-n, --limits <value>

Limite du nombre d'observations restitué par la commande

-E, --regex

Activation de l'utilisation d'expressions régulières

-b, --before

Regarder avant l'invocation

-e, --exception

Regarder après la levée d'une exception

-f, --finish

Regarder après l'invocation, activé par défaut

-M, --sizeLimit <value>

Taille maximale en octets du résultat affiché. Valeur par défaut : 10 * 1024 * 1024

-s, --success

Regarder après une invocation réussie

-x <value>

Niveau de profondeur lors du parcours des objets (la valeur par défaut est 1)


Il faut obligatoirement fournir au moins trois paramètres : le motif de la classe, le motif de la méthode et la ou les informations à surveiller. Dans l'exemple ci-dessous, c'est la valeur de retour de la méthode incrementer() de la classe fr.jmdoudoux.dej.Compteur qui est affichée à chaque invocation.

Résultat :
[arthas@9840]$ watch fr.jmdoudoux.dej.Compteur incrementer returnObj
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 13 ms.
ts=2020-02-20 21:39:07; [cost=0.125ms] result=@Integer[14950]
ts=2020-02-20 21:39:08; [cost=0.0683ms] result=@Integer[14951]
ts=2020-02-20 21:39:10; [cost=0.0515ms] result=@Integer[14952] 
 
[arthas@9840]$

Les éléments utilisables dans l'expression des éléments à observer sont notamment :

Variable

Rôle

params

Les paramètres

params[n]

Le paramètre n

returnObj

La valeur de retour

throwExp

L'exception levée

target

L'objet courant (this) sur laquelle la méthode est invoquée

"{params, returnObj}"

Les paramètres et la valeur de retour

"{params[0], returnObj}"

Le premier paramètre et la valeur de retour

clazz

Le nom pleinement qualifié de la classe

method

La signature de la méthode


Les valeurs qui ne peuvent pas être obtenue (par exemple, target sur une méthode statique ou returnObj alors que l'observation est faite avant l'invocation) sont null.

La commande s'exécute tant qu'elle n'est pas interrompue avec la combinaison de touches Ctrl + C.

L'option -n permet le nombre d'invocations à afficher avant d'arrêter l'exécution de la commande.

Résultat :
[arthas@9840]$ watch fr.jmdoudoux.dej.Compteur incrementer returnObj -n 1
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 16 ms.
ts=2020-02-20 21:41:31; [cost=0.0633ms] result=@Integer[14997]
Command execution times exceed limit: 1, so command will exit. You can set it with -n option. 
[arthas@9840]$

4 points de vue peuvent être utilisés lors de l'observation d'une méthode, chacune exprimée avec une option dédiée.

L'option -b demande l'observation avant l'invocation. Dans ce point de vue, la valeur de retour et l'exception levée sont toujours null

Résultat :
[arthas@9840]$ watch fr.jmdoudoux.dej.Service fabriquer '{params, returnObj}' -b -n 1
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 19 ms.
ts=2020-02-27 23:47:27; [cost=0.0379ms] result=@ArrayList[
    @Object[][isEmpty=false;size=2],
    null,
]
Command execution times exceed limit: 1, so command will exit. You can set it with -n option.
[arthas@9840]$

L'option -f demande l'observation après l'invocation : elle est activée par défaut.

L'option -s demande l'observation après une invocation réussie.

L'option -e demande l'observation après la levée d'une exception : seules les exécutions qui lèvent une exception sont observées :

Résultat :
[arthas@9840]$ watch fr.jmdoudoux.dej.Service fabriquer '{params, throwexp}' -e -n 1
 -x 3
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 38 ms.
ts=2020-02-25 01:04:42; [cost=0.1891ms] result=@ArrayList[
    @Object[][
        @String[nom4],
        @Integer[40],
    ],
    java.lang.IllegalArgumentException: nom invalide
        at fr.jmdoudoux.dej.Service.fabriquer(Service.java:29)
        at fr.jmdoudoux.dej.Service.traiter(Service.java:20)
        at fr.jmdoudoux.dej.ThreadService.run(ThreadService.java:24)
,
]
Command execution times exceed limit: 1, so command will exit. You can set it with -n option.
[arthas@9840]$

Il est possible de demander plusieurs points de vue pour une même invocation observée. Dans l'exemple ci-dessous, l'observation est faite avant et après l'exécution de la méthode.

Résultat :
[arthas@9840]$ watch fr.jmdoudoux.dej.Service fabriquer '{params, returnObj}' -b -s -n 2
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 19 ms.
ts=2020-02-27 23:51:48; [cost=0.0313ms] result=@ArrayList[
    @Object[][isEmpty=false;size=2],
    null,
]
ts=2020-02-27 23:51:48; [cost=5.645432150981E8ms] result=@ArrayList[
    @Object[][isEmpty=false;size=2],
    @AutreClasse[fr.jmdoudoux.dej.AutreClasse@11d6648a],
]
Command execution times exceed limit: 2, so command will exit. You can set it with -n option. 
[arthas@9840]$

Il est possible d'observer l'instance sur laquelle la méthode est invoquée

Résultat :
[arthas@9840]$ watch fr.jmdoudoux.dej.AutreClasse afficher 'target' -n 2
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 51 ms.
ts=2020-02-26 22:22:24; [cost=4.6029ms] result=@AutreClasse[
    dateCrea=@LocalDateTime[2020-02-26T22:22:24.304],
    nom=@String[nom1],
    taille=@Integer[10],
]
ts=2020-02-26 22:22:25; [cost=0.2278ms] result=@AutreClasse[
    dateCrea=@LocalDateTime[2020-02-26T22:22:25.794],
    nom=@String[nom3],
    taille=@Integer[30],
]
Command execution times exceed limit: 2, so command will exit. You can set it with -n option.
[arthas@9840]$

Il est possible d'observer un champ de l'instance sur laquelle la méthode est invoquée

Résultat :
[arthas@9840]$ watch fr.jmdoudoux.dej.AutreClasse afficher 'target.nom' -n 2
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 16 ms.
ts=2020-02-26 22:24:22; [cost=0.3027ms] result=@String[nom3]
ts=2020-02-26 22:24:24; [cost=0.2338ms] result=@String[nom2]
Command execution times exceed limit: 2, so command will exit. You can set it with -n option. 
[arthas@9840]$

L'option -x permet de préciser le niveau de profondeur de parcours et de restitution des objets observés.

Résultat :
[arthas@9840]$ watch fr.jmdoudoux.dej.Service fabriquer '{params, returnObj}' -x 1 -n 1
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 22 ms.
ts=2020-02-25 00:47:34; [cost=0.2728ms] result=@ArrayList[
    @Object[][isEmpty=false;size=2],
    @AutreClasse[fr.jmdoudoux.dej.AutreClasse@1d4537e5],
]
Command execution times exceed limit: 1, so command will exit. You can set it with -n option.
[arthas@21344]$ watch fr.jmdoudoux.dej.Service fabriquer '{params, returnObj}' -x 3 -n 1
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 29 ms.
ts=2020-02-25 00:47:44; [cost=0.2408ms] result=@ArrayList[
    @Object[][
        @String[nom2],
        @Integer[20],
    ],
    @AutreClasse[
        dateCrea=@LocalDateTime[
            MIN=@LocalDateTime[-999999999-01-01T00:00],
            MAX=@LocalDateTime[+999999999-12-31T23:59:59.999999999],
            serialVersionUID=@Long[6207766400415563566],
            date=@LocalDate[2020-02-25],
            time=@LocalTime[00:47:44.604],
        ],
        nom=@String[nom2],
        taille=@Integer[20],
    ],
]
Command execution times exceed limit: 1, so command will exit. You can set it with -n option. 
[arthas@9840]$

Il est possible de filtrer les invocations observées en passant la condition en quatrième paramètre.

Résultat :
[arthas@9840]$ watch fr.jmdoudoux.dej.Service fabriquer '{params, returnObj}' 'params[0]=="no
m3"' -n 1 -x 3
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 25 ms.
ts=2020-02-25 00:54:05; [cost=0.2447ms] result=@ArrayList[
    @Object[][
        @String[nom3],
        @Integer[30],
    ],
    @AutreClasse[
        dateCrea=@LocalDateTime[
            MIN=@LocalDateTime[-999999999-01-01T00:00],
            MAX=@LocalDateTime[+999999999-12-31T23:59:59.999999999],
            serialVersionUID=@Long[6207766400415563566],
            date=@LocalDate[2020-02-25],
            time=@LocalTime[00:54:05.288],
        ],
        nom=@String[nom3],
        taille=@Integer[30],
    ],
]
Command execution times exceed limit: 1, so command will exit. You can set it with -n option.
[arthas@9840]$

Dans l'exemple ci-dessous, le temps d'exécution des méthodes affichées doit être supérieur à 500ms.

Résultat :
[arthas@9840]$ watch fr.jmdoudoux.dej.Service fabriquer '{params, returnObj}' '#cost>500' -n 2
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 55 ms.
[arthas@20904]$ watch fr.jmdoudoux.dej.Service traiter '{params, returnObj}' '#cost>500' -n 2
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 16 ms.
ts=2020-02-27 23:00:30; [cost=1047.055101ms] result=@ArrayList[
    @Object[][isEmpty=true;size=0],
    @Integer[1374],
]
ts=2020-02-27 23:00:31; [cost=1049.916499ms] result=@ArrayList[
    @Object[][isEmpty=true;size=0],
    @Integer[1375],
]
Command execution times exceed limit: 2, so command will exit. You can set it with -n option. 
[arthas@9840]$

 

120.3.5.5. La commande tt

La commande tt (Time Tunnel) permet d'enregistrer les invocations de méthodes pour permettre leur analyse après la fin de l'enregistrement. Elle est particulièrement utile pour enregistrer de nombreuses invocations pour permettre leur analyse ultérieure. 

Chaque invocation enregistrée est appelée un time fragment qui possède un identifiant.

La syntaxe de la commande est de la forme :

tt [-d] [--delete-all] [-x <value>] [-h] [-i <value>] [-n <value>] [-l] [-p] [-E] [--replay-interval <value>] [--replay-times <value>] [-s <value>] [-M <value>] [-t] [-w <value>] [class-pattern] [method-pattern] [condition-express]

Plusieurs options sont utilisables dont :

Options

Rôle

<class-pattern>

Motif pour désigner la ou les classes concernées

<method-pattern>

Motif pour désigner la ou les méthodes concernées

<condition-express>

Expression conditionnelle au format ognl

-n, --limits <value>

Limite d'exécution de la commande

-E, --regex

Expression régulière

-d, --delete

Supprimer le time fragment dont l'identifiant est fourni

--delete-all

Supprimer tous les time fragments

-x, --expand <value>

Niveau de profondeur lors du parcours des objets (la valeur par défaut est 1)

-i, --index <value>

Afficher des informations sur le time fragment dont l'identifiant est fourni

-n, --limits <value>

Limiter le nombre d'exécutions enregistrées à celui fourni

-l, --list

Lister tous les time fragments

-p, --play

Réexécuter le time fragment dont l'identifiant est fourni

-s, --search-express <value>

Rechercher des time fragments en utilisant le format ognl

-M, --sizeLimit <value>

Taille maximale en octets du résultat affiché. Valeur par défaut : 10 * 1024 * 1024

-t, --time-tunnel

Enregistrer les invocations de méthodes dans des time fragments

-w, --watch-express <value>

Définir les informations affichées d'un time fragment en utilisant le format ognl


L'option -t permet de demander un enregistrement des invocations de méthodes dans un laps de temps.

Résultat :
[arthas@9840]$ tt -t fr.jmdoudoux.dej.Service traiter
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 59 ms.
 INDEX  TIMESTAMP        COST(m  IS-RE  IS-EX  OBJECT     CLASS            METHOD
                         s)      T      P
------------------------------------------------------------------------------------- 
 1000   2020-02-21 21:5  2063.1  true   false  NULL       Service          traiter
        9:06             742
 1001   2020-02-21 21:5  4039.0  true   false  NULL       Service          traiter
        9:08             635
 1002   2020-02-21 21:5  2038.6  true   false  NULL       Service          traiter
        9:16             877
 1003   2020-02-21 21:5  2037.9  true   false  NULL       Service          traiter
        9:16             356
 1004   2020-02-21 21:5  3040.0  true   false  NULL       Service          traiter
        9:20             753
[arthas@9840]$

Les informations affichées sont :

Colonne

Rôle

INDEX

Identifiant du fragment. Chaque invocation a son propre identifiant.

TIMESTAMP

Date/heure de la capture du fragment

COST(ms)

Temps d'exécution de la méthode

IS-RET

Est-ce que la méthode s'est correctement exécutée

IS-EXP

Est-ce que la méthode a levé une exception

OBJECT

Valeur retournée par la méthode hashCode() de l'objet sur lequel la méthode est invoquée. NULL si la méthode est statique

CLASS

La classe de la méthode exécutée

METHOD

La méthode exécutée


Il est possible d'interrompre la commande en utilisant la combinaison de touches Ctrl + C.

L'option -n de limiter le nombre de time fragments enregistrés durant l'exécution de la commande.

Résultat :
[arthas@9840]$ tt -t -n 3 fr.jmdoudoux.dej.Service traiter
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 19 ms.
 INDEX  TIMESTAMP        COST(m  IS-RE  IS-EX  OBJECT     CLASS           METHOD
                         s)      T      P
------------------------------------------------------------------------------------- 
 1000   2020-02-28 00:1  1048.5  true   false  NULL       Service         traiter
        9:18             577
 1001   2020-02-28 00:1  1053.8  true   false  NULL       Service         traiter
        9:19             442
 1002   2020-02-28 00:1  2039.6  true   false  NULL       Service         traiter
        9:21             496
Command execution times exceed limit: 3, so command will exit. You can set it with -n
 option.
[arthas@9840]$

Le nombre d'invocations capturées peut être important : il est possible de préciser en paramètre une condition de capture des invocations.

Résultat :
[arthas@9840]$ tt -t -n 2 fr.jmdoudoux.dej.Service traiter '#cost>2000'
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 16 ms.
 INDEX  TIMESTAMP        COST(m  IS-RE  IS-EX  OBJECT     CLASS           METHOD
                         s)      T      P
------------------------------------------------------------------------------------- 
 1004   2020-02-28 00:2  2038.7  true   false  NULL       Service         traiter
        4:08             198
 1005   2020-02-28 00:2  4034.7  true   false  NULL       Service         traiter
        4:11             803
Command execution times exceed limit: 2, so command will exit. You can set it with -n
 option.
[arthas@9840]$

Un fois l'enregistrement terminé, il est possible d'obtenir la liste des time fragments en utilisant l'option -l.

Résultat :
[arthas@9840]$ tt -l
 INDEX  TIMESTAMP        COST(m  IS-RE  IS-EX  OBJECT     CLASS           METHOD
                         s)      T      P
------------------------------------------------------------------------------------- 
 1000   2020-02-21 21:5  2063.1  true   false  NULL       Service         traiter
        9:06             742
 1001   2020-02-21 21:5  4039.0  true   false  NULL       Service         traiter
        9:08             635
 1002   2020-02-21 21:5  2038.6  true   false  NULL       Service         traiter
        9:16             877
 1003   2020-02-21 21:5  2037.9  true   false  NULL       Service         traiter
        9:16             356
 1004   2020-02-21 21:5  3040.0  true   false  NULL       Service         traiter
        9:20             753
Affect(row-cnt:5) cost in 5 ms. 
[arthas@9840]$

Il est possible d'obtenir des informations sur le contexte d'invocation d'un fragment particulier en utilisant l'option -i pour fournir l'identifiant du fragment

Résultat :
[arthas@9840]$ tt -i 1002
 INDEX         1002
 GMT-CREATE    2020-02-21 13:59:16
 COST(ms)      2038.6877
 OBJECT        NULL
 CLASS         fr.jmdoudoux.dej.Service
 METHOD        traiter
 IS-RETURN     true
 IS-EXCEPTION  false
 RETURN-OBJ    @Integer[125]
Affect(row-cnt:1) cost in 2 ms. 
[arthas@9840]$

Il est possible d'obtenir des informations choisies sur un fragment particulier en utilisant l'option -i pour fournir l'identifiant du fragment et l'option -w pour préciser les informations à obtenir (de manière similaire à celle de la commande watch)

Résultat :
[arthas@9840]$ tt -i 1002 -w '{params,returnObj}'
@ArrayList[
    @Object[][isEmpty=true;size=0],
    @Integer[125],
]
Affect(row-cnt:1) cost in 2 ms. 
[arthas@9840]$

L'option -s permet de chercher les invocations enregistrées d'une méthode particulière

Résultat :
[arthas@9840]$ tt -s 'method.name=="traiter"'
 INDEX  TIMESTAMP        COST(m  IS-RE  IS-EX  OBJECT     CLASS           METHOD
                         s)      T      P
------------------------------------------------------------------------------------- 
 1000   2020-02-21 21:5  2063.1  true   false  NULL       Service         traiter
        9:06             742
 1001   2020-02-21 21:5  4039.0  true   false  NULL       Service         traiter
        9:08             635
 1002   2020-02-21 21:5  2038.6  true   false  NULL       Service         traiter
        9:16             877
 1003   2020-02-21 21:5  2037.9  true   false  NULL       Service         traiter
        9:16             356
 1004   2020-02-21 21:5  3040.0  true   false  NULL       Service         traiter
        9:20             753
Affect(row-cnt:5) cost in 32 ms. 
[arthas@9840]$

Arthas conserve le contexte de chaque invocation : il est possible de réexécuter une exécution en utilisant les options -i pour préciser le fragment concerné via son identifiant et l'option -p.

Résultat :
[arthas@9840]$ tt -i 1002 -p
 RE-INDEX      1002
 GMT-REPLAY    2020-02-21 15:20:40
 OBJECT        NULL
 CLASS         fr.jmdoudoux.dej.Service
 METHOD        traiter
 IS-RETURN     true
 IS-EXCEPTION  false
 COST(ms)      4037.3472
 RETURN-OBJ    @Integer[1609]
Time fragment[1002] successfully replayed 1 times. 
[arthas@9840]$

Attention : la réexécution d'une méthode se fait dans un autre thread, ce qui implique un accès à un autre ThreadLocal si la méthode en a besoin.

 

120.3.5.6. La commande profiler

La commande profiler utilise async-profiler pour obtenir des informations de profiling et les restituer dans différents formats dont le frame graph.

La syntaxe de la commande est de la forme :

profiler [--allkernel] [--alluser] [-e <value>] [-f <value>] [--format <value>] [-h] [-i <value>] [--threads] action [actionArg]

Plusieurs options sont utilisables dont :

Options

Rôle

--allkernel

Prendre en compte uniquement les événements de type kernel-mode

--alluser

Prendre en compte uniquement les événements de type user-mode

-e, --event <value>

Préciser le type d'événements à profiler : (cpu, alloc, lock, cache-misses etc.), la valeur par défaut est cpu

-f, --file <value>

Préciser le chemin du fichier résultat

--format <value>

Préciser le format du fichier résultat (svg, html, jfr), la valeur par est svg

-i, --interval <value>

Préciser l'intervalle d'échantillonnage en ns (par défaut : 10000000 soit 10 ms)

--threads

Profiler les différents threads séparément

<action>

Préciser l'action à exécuter. Les valeurs possibles sont : resume, dumpCollapsed, getSamples, start, list, execute, version, stop, load, dumpFlat, actions, dumpTraces, status


L'action actions permet d'obtenir la liste des actions utilisables dans la commande.

Résultat :
[arthas@2884]$ profiler actions
Supported Actions: [resume, dumpCollapsed, getSamples, start, list, execute, version,
 stop, load, dumpFlat, actions, dumpTraces, status]
[arthas@2884]$ profiler version
1.7[arthas@2884]$

La commande profiler n'est pas utilisable sur toutes les plateformes : c'est notamment le cas sous Windows.

L'action list permet d'afficher tous les événements qui peuvent être mesurés.

Résultat :
[arthas@14128]$ profiler list
Current OS do not support AsyncProfiler, Only support Linux/Mac.

Sur les systèmes supportés l'option list permet d'afficher la liste de profilers utilisables. Par exemple, sous Linux :

Résultat :
[arthas@829]$ profiler list
Basic events:
  cpu
  alloc
  lock
  wall
  itimer
Perf events:
  page-faults
  context-switches
  cycles
  instructions
  cache-references
  cache-misses
  branches
  branch-misses
  bus-cycles
  L1-dcache-load-misses
  LLC-load-misses
  dTLB-load-misses
  mem:breakpoint
  trace:tracepoint
[arthas@829]$

Le plus simple pour démarrer le profiling est d'utiliser l'action start.

Résultat :
[arthas@2884]$ profiler start --event cpu
Started [cpu] profiling

Selon la configuration du système, la commande peut échouer. Par exemple, sous Linux :

Résultat :
[arthas@2884]$ profiler start
Perf events unavailable. See stderr of the target process.

Il faut consulter la console de l'application connectée.

Résultat :
WARNING: Kernel symbols are
unavailable due to restrictions. Try
 
echo 0 > /proc/sys/kernel/kptr_restrict
 
echo 1 > /proc/sys/kernel/perf_event_paranoid
perf_event_open failed: Permission
non accordée

Il faut alors suivre les instructions proposées dans la console de l'application connectée.

Résultat :
jm@VMUbuntu:~$ sudo sh
# echo 0 >
/proc/sys/kernel/kptr_restrict
# echo 1 >
/proc/sys/kernel/perf_event_paranoid
# exit
jm@VMUbuntu:~$

Une fois la configuration effectuée, il est possible de lancer le profiling.

Par défaut, le profiling se fait sur les événements de type cpu.

Résultat :
[arthas@2884]$ profiler start
Started [cpu] profiling

L'action status permet de connaître le type d'événements capturés et le temps d'exécution du profiling.

Résultat :
[arthas@2884]$ profiler status
[perf] profiling is running for 29
seconds

L'action getSamples permet de connaître le nombre de mesures effectuées.

Résultat :
[arthas@2884]$ profiler getSamples
243

L'action stop permet d'arrêter le profiling et de générer un fichier de résultat. Par défaut c'est un flame graph, il est au format SVG, stocké dans le sous-répertoire arthas-output et le chemin du fichier est affiché.

Résultat :
[arthas@2884]$ profiler stop
profiler output file:
/home/jm/arthas-output/20200423-131511.svg
OK
[arthas@2884]$

Il est possible de fournir le nom du fichier avec l'action stop en utilisant l'option -file

Résultat :
[arthas@2884]$ profiler stop --file
/tmp/mon_app_profilling.svg

Le format du fichier généré est par défaut SVG, mais il est possible d'utiliser d'autres formats comme HTML en utilisant l'option --format.

Résultat :
[arthas@2884]$ profiler stop
--format html

Il est possible de visualiser le résultat dans un navigateur. Par défaut, Arthas utilise le port 3658 et il suffit d'ouvrir l'URL http://localhost:3658/arthas-output/ 

En cliquant sur le résultat désiré, les informations sont affichées.

Il est possible de profiler d'autres événements et obtenir le résultat sous un autre format.

Résultat :
[arthas@2884]$ profiler start
--event alloc
Started [alloc] profiling
[arthas@2884]$ profiler stop
--format html
profiler output file:
/home/jm/arthas-output/20200423-135658.html
OK

L'action resume permet de démarrer un profiling en concervant les données capturées lors de la précédente commande stop.

L'action version affiche la version d'async-profiler utilisée.

 

120.4. L'exécution de commandes en asynchrone

Par défaut, toutes les commandes exécutées dans le CLI Arthas sont exécutées de manière synchrone : durant leur exécution, il n'est pas possible d'interagir avec le CLI pour par exemple exécuter une autre commande.

L'exécution de commandes en asynchrone peut être utile et pratique lorsqu'un problème est difficilement reproductible dans l'environnement.

Arthas permet l'exécution de commandes en arrière-plan (background) pour une exécution asynchrone. Le mode de fonctionnement de ce type d'exécution est inspiré de ce que propose Linux :

Fonctionnalité

Rôle

&

Exécution de la commande en arrière-plan

Redirection de la sortie d'une commande avec écrasement

>> 

Redirection de la sortie d'une commande

jobs

Afficher la liste des commandes exécutées en arrière-plan

kill

Forcer l'arrêt d'une tâche en arrière-plan

fg

Basculer une tâche en arrière-plan pour la remettre en premier plan

bg

Demander l'exécution d'une commande en arrière-plan


Les tâches en arrière-plan poursuivent leur exécution même si la session est déconnectée.

Attention : l'exécution de nombreuses tâches en arrière-plan peut avoir un impact sur les performances de la JVM sur laquelle Arthas est connecté.

 

120.4.1. L'exécution de commandes en arrière-plan

Pour exécuter une commande en arrière-plan, il suffit de terminer la commande par un caractère &.

Résultat :
[arthas@20904]$ tt -t -n 100 fr.jmdoudoux.dej.Service traiter '#cost>2000' &
[arthas@20904]$ Affect(class-cnt:1 , method-cnt:1) cost in 15 ms.
 INDEX  TIMESTAMP        COST(m  IS-RE  IS-EX  OBJECT    CLASS          METHOD
                         s)      T      P
------------------------------------------------------------------------------------- 
 1007   2020-02-28 00:3  2040.5  true   false  NULL      Service        traiter
        0:27             601
 1008   2020-02-28 00:3  3080.2  true   false  NULL      Service        traiter
        0:30             453

Une fois une commande exécutée en arrière-plan, il est possible d'exécuter d'autres commandes.

Il est préférable de rediriger la sortie d'une commande exécutée en arrière-plan pour éviter que celle-ci ne viennent perturber l'affichage dans la console.

 

120.4.2. La redirection de la sortie

Arthas permet de rediriger la sortie d'une commande en utilisant les opérateurs > ou >>. Ils peuvent être combinés avec l'opérateur & pour éviter de polluer la console avec les sorties d'une commande exécutée en arrière-plan.

Résultat :
[arthas@7656]$ tt -t fr.jmdoudoux.dej.Service traiter >> &
job id  : 11
cache location  : C:\Users\jm\logs\arthas-cache\7656\11
[arthas@7656]$

Si aucun chemin n'est précisé, Arthas redirige la sortie dans le cache local précisé avec la propriété « cache location ». Pour garantir l'unicité, le chemin contient le PID de la JVM et l'identifiant du job.

Il est possible de préciser le chemin d'un fichier qui va contenir la redirection : ce fichier est écrit sur la machine locale où est lancé la console Arthas.

Résultat :
[arthas@20904]$ tt -t fr.jmdoudoux.dej.Service traiter > log_tt.txt &
[arthas@20904]$

Pour enrichir le contenu du fichier existant, il faut un double caractère >.

Résultat :
[arthas@20904]$ tt -t fr.jmdoudoux.dej.Service traiter >> log_tt.txt &
[arthas@20904]$

Les commandes exécutées en arrière-plan poursuivent leur exécution dans la JVM même si la session est arrêtée.

Les commandes en arrière-plan ont un timeout défini par défaut à une journée grâce à l'option globale job-timeout. Cette valeur peut être modifiée avec la commande options.

 

120.4.3. Afficher la liste des tâches en arrière-plan

La commande jobs permet de lister toutes les commandes en cours d'exécution en arrière-plan.

Résultat :
[arthas@7656]$ jobs
[11]*
       Running           tt -t fr.jmdoudoux.dej.Service traiter >> &
       execution count : 26
       start time      : Sat Feb 22 01:26:55 CET 2020
       cache location  : C:\Users\jm\logs\arthas-cache\7656\11
       timeout date    : Sun Feb 23 01:26:55 CET 2020
       session         : 313bd832-8236-42cc-a81b-ac0641e2d5f6 (current)
[arthas@7656]$

La commande affiche plusieurs informations sur les tâches exécutées en arrière-plan :

 

120.4.4. L'arrêt d'une tâche en arrière-plan

Pour arrêter une tâche exécutée en arrière-plan, il faut utiliser la commande kill en lui passant en paramètre le job-id de la tâche concernée.

Résultat :
[arthas@7656]$ kill 11
kill job 11 success
[arthas@7656]$ jobs
[arthas@7656]$

 

120.5. Les scripts batch

Les scripts batch permettent d'exécuter plusieurs commandes contenues dans un fichier texte.

Le nom du fichier est libre.

Chaque commande doit être sur une ligne dédiée.

Il faut s'assurer que les commandes s'exécutent en mode batch et qu'elles sont configurées pour s'arrêter, par exemple :

Exemple dans un fichier script.as

Résultat :
session
thread -i 30000 -n 1
monitor fr.jmdoudoux.dej.Service traiter -c 5 -n 3

Pour exécuter le script, il faut lancer Arthas en utilisant en paramètre :

Résultat :
C:\java> java -jar arthas-boot.jar -f script.as 4192 > script.log
 
C:\java

Il est alors possible de consulter le résultat de l'exécution des commandes en consultant le fichier vers lequel la sortie standard a été redirigée.

 

120.6. La console web

Arthas propose une console web qui s'exécute dans un navigateur : les échanges se font en utilisant des websockets.

Une fois le client Arthas connecté à une JVM, il est possible d'ouvrir un navigateur en utilisant :

Le menu en haut permet de se connecter à un autre client en saisissant l'IP et le port et en cliquant sur le bouton « Connect ».

Une fois connectée, il est possible de saisir les commandes à exécuter.

 


Partie 17 : Les outils de profiling et monitoring 121. VisualVM Imprimer Index Index avec sommaire Télécharger le PDF    
Développons en Java
v 2.40   Copyright (C) 1999-2023 .