
JVMM (JVM Monitor) est un outil qui fournit une surveillance basée sur les services des machines virtuelles Java et des systèmes d'exploitation. It has rich data acquisition functions: OS (memory, CPU, disk status and IO, network card status and IO, etc.), JVM (memory, thread, thread pool, memory pool, GC, class loader, etc.), and also provides functions such as generating flame diagrams, hot updates of Java code, decompilation, etc. Suitable for use in scenarios such as service health monitoring, program tuning, problem investigation, performance tests, etc.
Veuillez aller dans les sorties pour télécharger la dernière version de JVMM et unzip It
Conseils: Certaines fonctions de JVMM dépendent de JDK dans l'environnement local. Veuillez vous assurer d'installer JDK au lieu de JRE dans votre environnement. Vérification simple: exécutez
jps -ldans votre environnement. S'il peut être exécuté normalement et sortira le résultat, cela signifie que l'environnement est OK, sinon JVMM peut ne pas être en mesure d'exécuter.
Tout d'abord, exécutez la commande suivante pour générer le package de pot de service
java -jar jvmm.jar -m jar -sPuis démarrez le serveur, veuillez faire attention à votre version JDK lors du démarrage
# 启动server,jdk 8使用下面命令
java -jar jvmm-server.jar
# jdk 9+ 为确保成功运行建议使用下面命令
java -jar --add-opens java.base/jdk.internal.loader=ALL-UNNAMED
--add-opens jdk.zipfs/jdk.nio.zipfs=ALL-UNNAMED
--add-opens java.base/java.net=ALL-UNNAMED
--add-opens java.management/sun.management=ALL-UNNAMED
jvmm-server.jarSi le serveur JVMM est démarré avec succès, il s'exécutera sur le port 5010 par défaut, puis vous devez configurer une nouvelle fenêtre dans le répertoire actuel à exécuter:
java -jar jvmm.jar -m client -a 127.0.0.1:5010 Si la connexion du serveur réussit, vous entrerez en mode client. Vous pouvez saisir la commande suivante pour collecter des données de processus. Bien sûr, vous pouvez entrer de help pour afficher l'utilisation de toutes les instructions exécutables dans ce mode.
info -t processVoici des exemples de données collectées en mode client JVMM. Les fonctions fournies par JVMM sont bien plus que cela. Pour plus de fonctions, veuillez lire la documentation d'utilisation de JVMM.
La fonction d'acquisition de données de base de JVMM est dans le module core , et la fonction orientée vers le service est dans le module server . Selon votre scénario d'utilisation, vous pouvez choisir les deux méthodes d'utilisation suivantes:
core (plus de fonctions) Tout d'abord, vous devez comprendre ce que le serveur peut faire? Le serveur fournit trois modes de service. Avant de l'utiliser, celui que vous devez choisir vous convient le mieux. Voici les trois modes de service:
Tout mode de service est inséparable à partir du fichier de configuration jvmm.yml. server.type est utilisé pour configurer le mode ou le mode que vous choisissez. Ils peuvent courir en même temps . Les configurations spécifiques de chaque mode correspondent à server.jvmm , server.http et server.sentinel .
server :
type : jvmm,http,sentinel # 支持同时开启多种模式
jvmm :
# ...
http :
# ...
sentinel :
# ...Pour la configuration par défaut, voir JVMM.YML et pour les informations de configuration, consultez les commentaires du fichier de configuration.
JVMM fournit quatre façons de démarrer votre serveur:
-javaagent Paramètre)jvmm-server.jar directement (les fonctions de mise à jour de la décompilation et du code ne prennent pas en charge)Avis! ! !
Quelle que soit la façon dont vous démarrez le serveur, si votre environnement d'exécution est JDK 9+ ou plus, il est recommandé d'ajouter les paramètres JVM suivants au démarrage pour assurer un fonctionnement réussi.
--add-opens java.base/jdk.internal.loader=ALL-UNNAMED
--add-opens jdk.zipfs/jdk.nio.zipfs=ALL-UNNAMED
--add-opens java.base/java.net=ALL-UNNAMED
--add-opens java.management/sun.management=ALL-UNNAMED
Exécutez JVMM.jar et sélectionnez Mode de fixation
java -jar jvmm.jar -m attach -c ./jvmm.ymlEnsuite, vous serez invité à sélectionner le numéro du processus cible. Après la sélection, le serveur sera démarré dans le processus cible.
Si vous connaissez déjà le PID du processus cible, vous pouvez le spécifier directement:
java -jar jvmm.jar -m attach -c ./jvmm.yml -pid 80080
Dans la méthode de l'agent Java, vous devez créer le package JAR requis et utiliser le paramètre -a pour spécifier l' agent de génération:
# 如果你的宿主程序中包含了 SLF4J 的实现(例如 logback),需要在生成时使用 -e 参数排除掉jvmm自带的 slf4j 实现
java -jar jvmm.jar -m jar -a -e logger
# 如果你的宿主程序中没有 SLF4J 的实现,无需排除 logger
java -jar jvmm.jar -m jar -a Après l'exécution, le fichier correspondant sera généré dans le même répertoire de niveau: jvmm-agent.jar , puis -javaagent est ajouté lors du démarrage du programme cible (en supposant qu'il est app.jar). Le format est le suivant:
java -javaagent:<jvmm-agent.jar路径>=config=<jvmm.yml路径> -jar your-app.jar
Par exemple:
java -javaagent:/path/jvmm-agent.jar=config=/path/jvmm.yml -jar app.jarPour être compatible avec la fonctionnalité de l'utilisation de serveurs externes, le format JavaAgent complet est:
-javaagent:<jvmm-agent.jar路径>=server=<jvmm-server.jar路径>;config=<jvmm.yml路径>
Lorsque votre programme commencera, JVMM commencera en tant qu'agent

Si vous ne souhaitez être attaché à aucun programme hôte, vous pouvez choisir de démarrer un serveur JVMM séparément, comme dans le scénario de surveillance d'une machine physique.
Tout d'abord, vous devez générer la dépendance du pot démarré et utiliser le paramètre -s pour spécifier le server de génération:
java -jar jvmm.jar -s Une fois l'exécution terminée, un jvmm-server.jar sera généré dans le même répertoire, puis le serveur sera démarré. Veuillez faire attention à votre version JDK au démarrage.
# 启动server,jdk 8使用下面命令
java -jar jvmm-server.jar
# jdk 9+ 为确保成功运行建议使用下面命令
java -jar --add-opens java.base/jdk.internal.loader=ALL-UNNAMED
--add-opens jdk.zipfs/jdk.nio.zipfs=ALL-UNNAMED
--add-opens java.base/java.net=ALL-UNNAMED
--add-opens java.management/sun.management=ALL-UNNAMED
jvmm-server.jarSi vous souhaitez utiliser Server dans votre projet, vous devez d'abord introduire les dépendances Maven
< dependencies >
< dependency >
< groupId >io.github.tzfun.jvmm</ groupId >
< artifactId >jvmm-server</ artifactId >
< version >${jvmm-version}</ version >
</ dependency >
<!-- jvmm日志依赖,如果你的项目中有 SLF4J、Log4J2、Log4J中任意一个依赖,可以去掉此依赖 -->
< dependency >
< groupId >io.github.tzfun.jvmm</ groupId >
< artifactId >jvmm-logger</ artifactId >
< version >${jvmm-version}</ version >
</ dependency >
</ dependencies >Démarrer le serveur avec une ligne de code
import org . beifengtz . jvmm . server . ServerBootstrap ;
public class Jvmm {
public static void main ( String [] args ) {
ServerBootstrap . getInstance (). start ();
}
} Bien sûr, la méthode de démarrage ci-dessus utilisera la configuration par défaut et nécessite généralement une configuration personnalisée. getInstance peut passer dans un org.beifengtz.jvmm.server.entity.conf.Configuration objet. La configuration personnalisée peut être implémentée en construisant une configuration.
Connectez JVMM Server ServerConveydemo.java à l'aide de JVMMConnector
Lorsque le serveur est démarré en mode jvmm ou http , vous pouvez appeler à distance l'interface intégrée.

Le service JVMM fournit les interfaces API suivantes:
| Taper | Données | Description |
|---|---|---|
| Jvmm_collect_sys_info | / / | Recueillir les informations du système d'exploitation |
| Jvmm_collect_sys_memory_info | / / | Collectez les données de mémoire du système d'exploitation |
| Jvmm_collect_sys_file_info | / / | Collectez les données d'utilisation de partition de disque d'exploitation du système d'exploitation |
| Jvmm_collect_process_info | / / | Collecter les données actuelles du processus |
| Jvmm_collect_disk_info | / / | Collectez les données de disque de machine physique |
| Jvmm_collect_disk_io_info | / / | Collecte les données de disque et de débit de la machine physique |
| Jvmm_collect_cpu_info | / / | Collectez les données de chargement du processeur de la machine physique |
| Jvmm_collect_network_info | / / | Collectez les informations de carte de réseau de machine physique et les données IO |
| Jvmm_collect_port_status | JSONArray, dont l'élément est le numéro de port | Collectez l'utilisation du port de machine physique |
| Jvmm_collect_jvm_classloading_info | / / | Collectez des informations de chargement de classe JVM |
| Jvmm_collect_jvm_classloader_info | / / | Collectez les informations de chargeur de classe JVM |
| Jvmm_collect_jvm_compilation_info | / / | Collecter des informations de compilation JVM |
| Jvmm_collect_jvm_gc_info | / / | Collectez les informations de collecteur de déchets JVM |
| Jvmm_collect_jvm_memory_manager_info | / / | Rassemblez les informations de gestion de la mémoire JVM |
| Jvmm_collect_jvm_memory_pool_info | / / | Collectez les informations sur le pool de mémoire JVM |
| Jvmm_collect_jvm_memory_info | / / | Collectez l'utilisation de la mémoire JVM |
| Jvmm_collect_jvm_thread_info | / / | Collectez les statistiques du thread JVM |
| Jvmm_collect_jvm_thread_stack | Voir ThreadInfodto | Collecte les données de pile de threads JVM spécifiées |
| Jvmm_collect_jvm_thread_detail | JSONArray, dont l'élément est un identifiant de fil | Collectez les détails du thread JVM (temps de processeur, temps de bloc, verrouillage, etc.) |
| Jvmm_collect_jvm_thread_pool | JSONObject, ses propriétés sont: classloadherHash (String), Clazz (String), instanceField (String), Field (String) | Collectez les informations sur le pool de threads JVM |
| Jvmm_collect_jvm_thread_ordered_cpu_time | JSONObject, ses propriétés sont: Type (String, Stack | info), DurationsCondes (int) | Acquisition de l'utilisation du processeur dans les threads JVM dans un certain temps |
| Jvmm_collect_jvm_dump_thread | / / | vider toutes les données de pile de threads |
| Jvmm_collect_batch | CollectionType [] | Collecte de données en lots en fonction des options |
| JVMM_EXECUTE_GC | / / | Exécuter GC |
| Jvmm_execute_java_process | / / | Liste tous les processus Java |
| JVMM_EXECUTE_JVM_TOOL | Chaîne | Exécuter la commande d'outil JVM |
| JVMM_EXECUTE_JAD | JSONObject, ses propriétés sont: ClassName (String), méthodyName (String) | Décompilation du code (seuls les agents sont pris en charge) |
| JVMM_EXECUTE_LOAD_PATCH | JSONArray, dont l'élément est patchdto | Code des mises à jour chaudes. Lorsque vous spécifiez le hachage de Classloader, ce ne sont que des mises à jour chaudes pour modifier la classe chargée par Classloader. |
| JVMM_EXECUTE_SWITCHES_GET | / / | Obtenez les informations du commutateur d'acquisition |
| JVMM_EXECUTE_SWITCHES_SET | JSONObject, ses propriétés sont: noms (commutateurs []), Open (Boolean) | Configurer le commutateur d'acquisition |
| Jvmm_profiler_sample | Voir profilersampledto | Générer une carte de flamme |
| Jvmm_profiler_execute | Chaîne | Exécuter la commande Profiler, voir Async-Profiler |
| Jvmm_profiler_start | Voir ProfilersampledTo, où seul eventcounterinteval est valide | Exécuter la commande Profiler Start Sampling |
| Jvmm_profiler_stop | String, champ de format dans ProfilersampledTo, la valeur facultative est htmltxtjfr | Exécutez le profileur pour mettre fin à l'échantillonnage et à la commande de fichiers d'exportation |
| Jvmm_profiler_status | / / | Obtenez le statut de profileur actuel |
| Jvmm_profiler_list_events | / / | Obtenez les événements de profileur soutenus par l'environnement actuel |
| Jvmm_server_shutdown | Chaîne | Fermer le service, les données sont le type de service |

Le service HTTP fournit les interfaces API suivantes:
| Uri | méthode | paramètre | Corps | décrire |
|---|---|---|---|---|
| / Collect / Process | OBTENIR | / / | / / | Collecter des informations de processus |
| / Collect / Disk | OBTENIR | / / | / / | Collectez les données de disque de machine physique |
| / Collect / disk_io | OBTENIR | / / | / / | Collecte les données de disque et de débit de la machine physique |
| / Collect / CPU | OBTENIR | / / | / / | Collectez les données de chargement du processeur de la machine physique |
| / Collect / Network | OBTENIR | / / | / / | Collectez les informations de carte de réseau de machine physique et les données IO |
| / Collect / Sys | OBTENIR | / / | / / | Recueillir les informations du système d'exploitation |
| / collection / sys / mémoire | OBTENIR | / / | / / | Collectez les données de mémoire du système d'exploitation |
| / Collect / sys / fichier | OBTENIR | / / | / / | Collectez les données d'utilisation de partition de disque d'exploitation du système d'exploitation |
| / Collect / Port | OBTENIR | ports (int []) | / / | Acquisition de l'occupation du port du système d'exploitation |
| / Collect / JVM / Classloading | OBTENIR | / / | / / | Collectez des informations de chargement de classe JVM |
| / collection / jvm / classloader | OBTENIR | / / | / / | Collectez les informations de chargeur de classe JVM |
| / collection / jvm / compilation | OBTENIR | / / | / / | Collecter des informations de compilation JVM |
| / Collect / JVM / GC | OBTENIR | / / | / / | Collectez les informations de collecteur de déchets JVM |
| / Collect / JVM / Memory_Manager | OBTENIR | / / | / / | Rassemblez les informations de gestion de la mémoire JVM |
| / Collect / JVM / Memory_Pool | OBTENIR | / / | / / | Collectez les informations sur le pool de mémoire JVM |
| / collection / jvm / mémoire | OBTENIR | / / | / / | Collectez l'utilisation de la mémoire JVM |
| / collection / jvm / thread | OBTENIR | / / | / / | Collectez les statistiques du thread JVM |
| / collection / jvm / thread_stack | POSTE | / / | Voir ThreadInfodto | Collecte les données de pile de threads JVM spécifiées |
| / Collect / JVM / Dump_thread | OBTENIR | / / | / / | vider toutes les données de pile de threads |
| / collection / jvm / thread_ordred_cpu_time | OBTENIR | Type (String, Stack | info), DurationsCondes (int) | / / | Acquisition de l'utilisation du processeur dans les threads JVM dans un certain temps |
| / collection / jvm / thread_detail | OBTENIR | id (long []) | / / | Collectez les détails du thread JVM (temps de processeur, temps de bloc, verrouillage, etc.) |
| / collection / jvm / thread_pool | OBTENIR | classloadherHash (String), Clazz (String), instanceField (String), Field (String) | / / | Collectez les informations sur le pool de threads JVM |
| / collection / by_options | OBTENIR | Options (CollectionType []) | Collecte de données en lots en fonction des options | |
| / Exécuter / GC | OBTENIR | / / | / / | Exécuter GC |
| / EXECUTE / JPS | OBTENIR | / / | / / | Liste tous les processus Java |
| / exécuter / jvm_tool | POSTE | / / | Commande (String) | Exécuter la commande d'outil JVM |
| / Exécuter / Jad | OBTENIR | className (string), méthodyname (string) | / / | Décompilation du code (seuls les agents sont pris en charge) |
| / exécuter / load_patch | POSTE | / / | JSONArray, dont l'élément est patchdto | Code des mises à jour chaudes. Lorsque vous spécifiez le hachage de Classloader, ce ne sont que des mises à jour chaudes pour modifier la classe chargée par Classloader. |
| / exécuter / get_switches | OBTENIR | / / | / / | Obtenez les informations du commutateur d'acquisition |
| / exécuter / set_switches | OBTENIR | Noms (commutateurs []), Open (Boolean) | / / | Configurer le commutateur d'acquisition |
| / Profiler / Flame_graph | POSTE | / / | Voir profilersampledto | Générer une carte de flamme |
| / Profiler / Start | POSTE | / / | Voir ProfilersampledTo, où seul eventcounterinteval est valide | Exécuter la commande Profiler Start Sampling |
| / Profiler / Stop | POSTE | / / | String, champ de format dans ProfilersampledTo, la valeur facultative est htmltxtjfr | Exécutez le profileur pour mettre fin à l'échantillonnage et à la commande de fichiers d'exportation |
| / profil / statut | OBTENIR | / / | / / | Obtenez le statut de profileur actuel |
| / Profiler / list_events | OBTENIR | / / | / / | Obtenez les événements de profileur soutenus par l'environnement actuel |
| / profil / exécuter | POSTE | / / | Commande (String) | Exécuter la commande Profiler, voir Async-Profiler |
| / serveur / arrêt | OBTENIR | Target (String) | / / | Fermer le service, les données sont le type de service |

La logique de fonctionnement du mode Sentinel est de collecter régulièrement des éléments de données spécifiés, puis de les pousser vers les abonnés . Vous devez fournir un service d'abonnement (interface HTTP) qui peut recevoir des données. Si l'accès à l'interface nécessite une authentification d'identité, l'interface HTTP abonnée ne prend actuellement en charge que l'authentification de base .
Configuration du mode sentinelle
server :
type : sentinel
sentinel :
- subscribers :
# publish jvmm data to custom http server
- type : http
url : http://127.0.0.1:9999/monitor/subscriber
auth :
enable : true
username : 123456
password : 123456
# publish jvmm data to prometheus
- type : prometheus
url : http://127.0.0.1:9090/api/v1/write
auth :
enable : true
username : 123456
password : 123456
interval : 15
tasks :
- process
- disk
- disk_io
- cpu
- port
...Un total des articles de collecte suivants sont pris en charge:
[
" process " ,
" disk " ,
" disk_io " ,
" cpu " ,
" network " ,
" sys " ,
" sys_memory " ,
" sys_file " ,
" port " ,
" jvm_classloading " ,
" jvm_classloader " ,
" jvm_compilation " ,
" jvm_gc " ,
" jvm_memory " ,
" jvm_memory_manager " ,
" jvm_memory_pool " ,
" jvm_thread " ,
" jvm_thread_stack " ,
" jvm_thread_detail " ,
" jvmm_thread_pool "
]Actuellement, seuls les éléments de collection suivants prennent en charge Prometheus
[
" process " ,
" disk_io " ,
" cpu " ,
" network " ,
" sys " ,
" sys_memory " ,
" sys_file " ,
" jvm_classloading " ,
" jvm_compilation " ,
" jvm_gc " ,
" jvm_memory " ,
" jvm_memory_pool " ,
" jvm_thread "
]JVMM fournit deux tableaux de bord de modèle Grafana, à savoir: Node et JVM
Le modèle de nœud est une collection d'éléments de surveillance liés au système, ce qui peut vous aider à vous concentrer davantage sur la surveillance des données des machines physiques ou des hôtes cloud.


Méthode d'importation: Importer l'ID de tableau de bord 20430 ou importer le tableau de bord-Node.json
Pour coopérer avec ce modèle, les tâches suivantes doivent être configurées:
[
" process " ,
" disk_io " ,
" cpu " ,
" network " ,
" sys " ,
" sys_memory " ,
" sys_file "
]Le modèle JVM est une collection d'éléments de surveillance liés à JVM, ce qui peut vous aider à vous concentrer davantage sur les données de surveillance du processus.


Méthode d'importation: IDME IDMORD ID de tableau de bord 20429 ou importez le tableau de bord-jvm.json
Pour coopérer avec ce modèle, les tâches suivantes doivent être configurées:
[
" process " ,
" jvm_classloading " ,
" jvm_compilation " ,
" jvm_gc " ,
" jvm_memory " ,
" jvm_memory_pool " ,
" jvm_thread "
]Si vous souhaitez développer un secondaire basé sur JVMM, il vous suffit d'introduire des dépendances de base
< dependency >
< groupId >io.github.tzfun.jvmm</ groupId >
< artifactId >jvmm-core</ artifactId >
< version >${jvmm-version}</ version >
</ dependency > Toutes les interfaces fonctionnelles d'acquisition de données fournies par le serveur précédent et d'autres interfaces fonctionnelles qui ne fournissent pas d'interfaces d'appel à distance peuvent être obtenues via une classe d'usine: org.beifengtz.jvmm.core.JvmmFactory
public class Jvmm {
public static void main ( String [] args ) {
// 提供所有的数据采集接口
JvmmCollector collector = JvmmFactory . getCollector ();
// 提供所有的执行接口
JvmmExecutor executor = JvmmFactory . getExecutor ();
// 提供火焰图生成器
JvmmProfiler profiler = JvmmFactory . getProfiler ();
}
}L'outil client JVMM offre un moyen simple et rapide d'appeler à distance JVMM. Bien sûr, il entreprend également des fonctions importantes telles que Pider Server et générer des pots de dépendance.
L'outil client fournit une fonction d'exécution de la commande bootstrap et il sera exécuté enquête même si vous ne prenez aucun paramètre. Pour une utilisation spécifique, veuillez utiliser la commande suivante pour afficher le document d'aide:
java -jar jvmm.jar -hExemple d'acquisition de données par outil client
Générer un exemple de diagramme de flamme

Exemple d'appel de code
Exemple d'application de tableau de bord personnalisé

Certains composants à l'intérieur du projet peuvent être utilisés sans le projet, léger et facile à utiliser
La raison en est que votre environnement ne dispose pas d'outils JDK ou des variables d'environnement. Veuillez vous assurer que votre environnement est installé avec JDK au lieu de JRE. Vérification simple: exécutez jps -l dans votre environnement, et si elle peut être exécutée normalement et publier le résultat, cela signifie que l'environnement est OK.
Solution: Configurez votre répertoire JDK bin local comme variable d'environnement
Si vous démarrez JVMM-Server.jar, la raison en est que vous utilisez JDK 9 et plus, Java interdit l'accès réfléchissant à certaines classes à commencer par JDK 9+.
java.lang.reflect.InaccessibleObjectException: Unable to make field final jdk.internal.loader.URLClassPath jdk.internal.loader.ClassLoaders$AppClassLoader.ucp accessible: module java.base does not "opens jdk.internal.loader" to unnamed module @2d127a61
Solution: ajouter les paramètres de machine virtuelle suivantes
# JDK 9+ 为确保成功运行建议设置以下几个虚拟机参数
# --add-opens java.base/jdk.internal.loader=ALL-UNNAMED
# --add-opens jdk.zipfs/jdk.nio.zipfs=ALL-UNNAMED
# --add-opens java.base/java.net=ALL-UNNAMED
# --add-opens java.management/sun.management=ALL-UNNAMED
java -jar --add-opens java.base/jdk.internal.loader=ALL-UNNAMED
--add-opens jdk.zipfs/jdk.nio.zipfs=ALL-UNNAMED
--add-opens java.base/java.net=ALL-UNNAMED
--add-opens java.management/sun.management=ALL-UNNAMED
jvmm-server.jar ./jvmm.yml Si vous n'invitez No access to perf events. Try --fdtransfer or --all-user option or 'sysctl kernel.perf_event_paranoid=1' , la raison en est que le noyau système interdit la détection des performances du système par défaut, et vous devez activer cette option.
sudo systcl -w kernel.perf_event_paranoid=1Ou modifier le fichier sysctl
sudo sh -c ' echo "kernel.perf_event_paranoid=1" >> /etc/sysctl.conf '
sudo sysctl -pCet outil est entièrement open source et gratuit, et il n'est pas facile à créer. Si vous pensez que c'est bien, vous pouvez faire un don pour soutenir ce projet.
Liste des dons:
Si vous rencontrez des problèmes pendant l'utilisation, ou si vous avez des idées ou des suggestions uniques sur ce projet, veuillez me soumettre un problème ou m'envoyer un message privé
Courriel: [email protected]
WeChat: Beifeng-TZ (veuillez noter JVMM si vous l'ajoutez)