Développons en Java 2.30 | |
Copyright (C) 1999-2022 Jean-Michel DOUDOUX | (date de publication : 15/06/2022) |
|
Niveau : | 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 :
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é.
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 |
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.
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.
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
|
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 |
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/
|
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 |
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
|
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
|
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 :
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.
|
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 |
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.
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]$
|
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]$ |
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]$ |
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]$ |
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]$ |
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]
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]$ |
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]$ |
La commande affiche la version de la CLI.
Résultat : |
[arthas@14128]$ version
3.1.7
[arthas@14128]$ |
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]$ |
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]$ |
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]$ |
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 |
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.
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]$ |
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.
|
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 :
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
|
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
|
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]$ |
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.
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]$ |
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 |
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]$ |
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]$ |
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.
|
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]$ |
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]$ |
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.
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]$ |
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é.
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]$ |
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.
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.
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]$ |
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]$ |
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]$ |
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.
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/jumbo/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/jumbo/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.
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é.
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.
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.
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 :
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]$ |
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.
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.
|