
JVMM (JVM Monitor) es una herramienta que proporciona monitoreo basado en servicios de máquinas virtuales y sistemas operativos Java. 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 testing, etc.
Vaya a lanzamientos para descargar la última versión de JVMM y descifrar IT
Consejos: algunas funciones de JVMM dependen de JDK en el entorno local. Asegúrese de instalar JDK en lugar de solo JRE en su entorno. Verificación simple: ejecute
jps -len su entorno. Si se puede ejecutar normalmente y emitir el resultado, significa que el entorno está bien, de lo contrario, JVMM puede no ser capaz de ejecutarse.
Primero, ejecute el siguiente comando para generar el paquete JAR de servicio
java -jar jvmm.jar -m jar -sLuego inicie el servidor, preste atención a su versión JDK al comenzar
# 启动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 el servidor JVMM se inicia correctamente, se ejecutará en el puerto 5010 de forma predeterminada y luego debe configurar una nueva ventana en el directorio actual para ejecutar:
java -jar jvmm.jar -m client -a 127.0.0.1:5010 Si la conexión del servidor es exitosa, ingresará al modo cliente. Puede ingresar el siguiente comando para recopilar datos de proceso. Por supuesto, puede ingresar help para ver el uso de todas las instrucciones ejecutables en este modo.
info -t processAquí hay ejemplos de datos recopilados en modo cliente JVMM. Las funciones proporcionadas por JVMM son mucho más que eso. Para obtener más funciones, lea la documentación de uso de JVMM.
La función de adquisición de datos básicas de JVMM está en el módulo core , y la función orientada al servicio se encuentra en el módulo server . De acuerdo con su escenario de uso, puede elegir los siguientes dos métodos de uso:
core (más funciones) En primer lugar, ¿necesita entender qué puede hacer el servidor? El servidor proporciona tres modos de servicio. Antes de usarlo, cuál debe elegir es más adecuado para usted. Aquí están los tres modos de servicio:
Cualquier modo de servicio es inseparable del archivo de configuración JVMM.YML. server.type se usa para configurar qué modo o qué modo elige. Pueden correr al mismo tiempo . Las configuraciones específicas de cada modo corresponden a server.jvmm , server.http y server.sentinel .
server :
type : jvmm,http,sentinel # 支持同时开启多种模式
jvmm :
# ...
http :
# ...
sentinel :
# ...Para la configuración predeterminada, consulte JVMM.YML, y para la información de configuración, consulte los comentarios en el archivo de configuración.
JVMM proporciona cuatro formas de iniciar su servidor:
-javaagent Parameter)jvmm-server.jar directamente (las funciones de actualización de descompilación y código de código no admiten)¡Aviso! ! !
No importa de qué manera inicie el servidor, si su entorno en ejecución es JDK 9+ o superior, se recomienda agregar los siguientes parámetros JVM al inicio para garantizar una operación exitosa.
--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
Ejecute jvmm.jar y seleccione Adjuntar modo
java -jar jvmm.jar -m attach -c ./jvmm.ymlLuego se le solicitará que seleccione el número del proceso de destino. Después de seleccionar, el servidor se iniciará en el proceso de destino.
Si ya conoce el PID del proceso de destino, puede especificarlo directamente:
java -jar jvmm.jar -m attach -c ./jvmm.yml -pid 80080
En el método del agente Java, debe crear el paquete JAR requerido y usar el parámetro -a para especificar el agent de generación:
# 如果你的宿主程序中包含了 SLF4J 的实现(例如 logback),需要在生成时使用 -e 参数排除掉jvmm自带的 slf4j 实现
java -jar jvmm.jar -m jar -a -e logger
# 如果你的宿主程序中没有 SLF4J 的实现,无需排除 logger
java -jar jvmm.jar -m jar -a Después de la ejecución, el archivo correspondiente se generará en el mismo directorio de nivel: jvmm-agent.jar , y luego se agrega -javaagent al comenzar el programa de destino (suponiendo que sea app.jar). El formato es el siguiente:
java -javaagent:<jvmm-agent.jar路径>=config=<jvmm.yml路径> -jar your-app.jar
Por ejemplo:
java -javaagent:/path/jvmm-agent.jar=config=/path/jvmm.yml -jar app.jarPara ser compatible con la funcionalidad de usar servidores externos, el formato Javaagent completo es:
-javaagent:<jvmm-agent.jar路径>=server=<jvmm-server.jar路径>;config=<jvmm.yml路径>
Cuando comience su programa, JVMM comenzará como agente

Si no desea estar adjunto a ningún programa de host, puede optar por iniciar un servidor JVMM por separado, como en el escenario de monitorear una máquina física.
Primero, debe generar la dependencia de JAR iniciada y usar el parámetro -s para especificar el server de generación:
java -jar jvmm.jar -s Una vez completada la ejecución, se generará un jvmm-server.jar en el mismo directorio, y luego se iniciará el servidor. Preste atención a su versión JDK al comenzar.
# 启动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 desea usar el servidor en su proyecto, primero debe introducir dependencias de 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 >Inicie el servidor con una línea de código
import org . beifengtz . jvmm . server . ServerBootstrap ;
public class Jvmm {
public static void main ( String [] args ) {
ServerBootstrap . getInstance (). start ();
}
} Por supuesto, el método de inicio anterior utilizará la configuración predeterminada y generalmente requiere una configuración personalizada. getInstance puede pasar a un org.beifengtz.jvmm.server.entity.conf.Configuration Object. La configuración personalizada se puede implementar construyendo la configuración.
Conecte JVMM Server ServerConveyDemo.java usando JVMMConnector
Cuando el servidor se inicia en modo jvmm o http , puede llamar de forma remota a la interfaz incorporada.

El servicio JVMM proporciona las siguientes interfaces API:
| Tipo | Datos | Descripción |
|---|---|---|
| Jvmm_collect_sys_info | / | Recopilar información del sistema operativo |
| Jvmm_collect_sys_memory_info | / | Recopilar datos de memoria del sistema operativo |
| Jvmm_collect_sys_file_info | / | Recopilar datos de uso de la partición del disco del sistema operativo |
| Jvmm_collect_process_info | / | Recopilar datos de proceso actuales |
| Jvmm_collect_disk_info | / | Recopilar datos de disco de máquina física |
| Jvmm_collect_disk_io_info | / | Recopilar el disco IO y los datos de rendimiento de la máquina física |
| Jvmm_collect_cpu_info | / | Recopilar datos de carga de CPU de la máquina física |
| Jvmm_collect_network_info | / | Recopilar información de tarjeta de red de máquina física y datos de IO |
| Jvmm_collect_port_status | JSONArray, cuyo elemento es el número de puerto | Recoger el uso del puerto de máquina física |
| Jvmm_collect_jvm_classloading_info | / | Recopilar información de carga de clase JVM |
| Jvmm_collect_jvm_classloader_info | / | Recopilar información de cargador de clase JVM |
| Jvmm_collect_jvm_compilation_info | / | Recopilar información de compilación JVM |
| Jvmm_collect_jvm_gc_info | / | Recopilar información de recolector de basura JVM |
| Jvmm_collect_jvm_memory_manager_info | / | Recopilar información del administrador de memoria JVM |
| Jvmm_collect_jvm_memory_pool_info | / | Recopilar información de grupo de memoria JVM |
| Jvmm_collect_jvm_memory_info | / | Recopilar el uso de la memoria JVM |
| Jvmm_collect_jvm_thread_info | / | Recopilar estadísticas de hilo JVM |
| Jvmm_collect_jvm_thread_stack | Ver ThreadInfodto | Recopilar los datos especificados de la pila de subprocesos JVM |
| Jvmm_collect_jvm_thread_detail | JSONArray, cuyo elemento es la identificación del hilo | Recopile detalles del hilo JVM (tiempo de CPU, tiempo de bloque, cerraduras, etc.) |
| Jvmm_collect_jvm_thread_pool | JSONObject, sus propiedades son: ClassLoaderHash (String), Clazz (String), InstanceField (String), Field (String) | Recopilar información de la piscina de hilos JVM |
| Jvmm_collect_jvm_thread_ordered_cpu_time | JSONObject, sus propiedades son: tipo (cadena, pila | información), Durationseconds (int) | Adquisición del uso de la CPU en hilos JVM dentro de un tiempo determinado |
| Jvmm_collect_jvm_dump_thread | / | Volcar todos los datos de la pila de subprocesos |
| Jvmm_collect_batch | CollectionType [] | Recopilación de datos en lotes basados en opciones |
| JVMM_EXECUTE_GC | / | Ejecutar GC |
| Jvmm_execute_java_process | / | Enumere todos los procesos de Java |
| JVMM_EXECUTE_JVM_TOOL | Cadena | Ejecutar el comando de herramienta jvm |
| JVMM_EXECUTE_JAD | JSONObject, sus propiedades son: ClassName (String), MethodName (String) | Descompilación de código (solo los agentes son compatibles) |
| Jvmm_execute_load_patch | JSONArray, cuyo elemento es PatchDTO | Código de actualizaciones en caliente. Al especificar el hash de ClassLoader, solo son actualizaciones en caliente para cambiar la clase Cargada por ClassLoader. |
| Jvmm_execute_switches_get | / | Obtenga la información del interruptor de adquisición |
| Jvmm_execute_switches_set | JSONObject, sus propiedades son: nombres (conmutadores []), abiertos (boolean) | Configurar el interruptor de adquisición |
| Jvmm_profiler_sample | Ver Profilersampledto | Generar mapa de llama |
| JVMM_Profiler_Execute | Cadena | Ejecutar el comando Profiler, ver Async-Profiler |
| Jvmm_profiler_start | Ver Profilersampledto, donde solo eventcounterinteval Field es válido | Ejecutar el comando de muestreo de inicio del perfiler |
| Jvmm_profiler_stop | Cadena, campo de formato en perfilers muestreado, el valor opcional es htmltxtjfr | Ejecutar el Profiler para finalizar el comando de archivo de muestreo y exportación |
| Jvmm_profiler_status | / | Obtenga el estado actual del perfilador |
| Jvmm_profiler_list_events | / | Obtenga los eventos de Profiler respaldados por el entorno actual |
| Jvmm_server_shutdown | Cadena | Cerrar el servicio, los datos son el tipo de servicio |

El servicio HTTP proporciona las siguientes interfaces API:
| Uri | método | parámetro | Cuerpo | describir |
|---|---|---|---|---|
| /coleccionar/procesar | CONSEGUIR | / | / | Recopilar información del proceso |
| /recoger/disco | CONSEGUIR | / | / | Recopilar datos de disco de máquina física |
| /coleccionar/disk_io | CONSEGUIR | / | / | Recopilar el disco IO y los datos de rendimiento de la máquina física |
| /coleccionar/CPU | CONSEGUIR | / | / | Recopilar datos de carga de CPU de la máquina física |
| /recopilar/red | CONSEGUIR | / | / | Recopilar información de tarjeta de red de máquina física y datos de IO |
| /coleccionar/sys | CONSEGUIR | / | / | Recopilar información del sistema operativo |
| /coleccionar/sys/memoria | CONSEGUIR | / | / | Recopilar datos de memoria del sistema operativo |
| /coleccionar/sys/archivo | CONSEGUIR | / | / | Recopilar datos de uso de la partición del disco del sistema operativo |
| /coleccionar/puerto | CONSEGUIR | puertos (int []) | / | Adquisición de la ocupación portuaria del sistema operativo |
| /coleccionar/jvm/carga de clases | CONSEGUIR | / | / | Recopilar información de carga de clase JVM |
| /coleccionar/jvm/classloader | CONSEGUIR | / | / | Recopilar información de cargador de clase JVM |
| /coleccionar/jvm/compilación | CONSEGUIR | / | / | Recopilar información de compilación JVM |
| /coleccionar/jvm/gc | CONSEGUIR | / | / | Recopilar información de recolector de basura JVM |
| /coleccionar/jvm/memoria_manager | CONSEGUIR | / | / | Recopilar información del administrador de memoria JVM |
| /coleccionar/jvm/memoria_pool | CONSEGUIR | / | / | Recopilar información de grupo de memoria JVM |
| /coleccionar/jvm/memoria | CONSEGUIR | / | / | Recopilar el uso de la memoria JVM |
| /coleccionar/jvm/hilo | CONSEGUIR | / | / | Recopilar estadísticas de hilo JVM |
| /coleccionar/jvm/thread_stack | CORREO | / | Ver ThreadInfodto | Recopilar los datos especificados de la pila de subprocesos JVM |
| /coleccionar/jvm/dump_thread | CONSEGUIR | / | / | Volcar todos los datos de la pila de subprocesos |
| /coleccionar/jvm/thread_ordered_cpu_time | CONSEGUIR | Tipo (String, Stack | Info), Durationseconds (int) | / | Adquisición del uso de la CPU en hilos JVM dentro de un tiempo determinado |
| /coleccionar/jvm/thread_detail | CONSEGUIR | id (largo []) | / | Recopile detalles del hilo JVM (tiempo de CPU, tiempo de bloque, cerraduras, etc.) |
| /coleccionar/jvm/thread_pool | CONSEGUIR | ClassLoLoaderHash (String), Clazz (String), InstanceField (String), Field (String) | / | Recopilar información de la piscina de hilos JVM |
| /coleccionar/by_options | CONSEGUIR | Opciones (CollectionType []) | Recopilación de datos en lotes basados en opciones | |
| /ejecutar/gc | CONSEGUIR | / | / | Ejecutar GC |
| /ejecutar/jps | CONSEGUIR | / | / | Enumere todos los procesos de Java |
| /ejecutar/jvm_tool | CORREO | / | comando (cadena) | Ejecutar el comando de herramienta jvm |
| /ejecutar/jad | CONSEGUIR | className (String), MethodName (String) | / | Descompilación de código (solo los agentes son compatibles) |
| /ejecutar/load_patch | CORREO | / | JSONArray, cuyo elemento es PatchDTO | Código de actualizaciones en caliente. Al especificar el hash de ClassLoader, solo son actualizaciones en caliente para cambiar la clase Cargada por ClassLoader. |
| /ejecutar/get_switches | CONSEGUIR | / | / | Obtenga la información del interruptor de adquisición |
| /ejecutar/set_switches | CONSEGUIR | nombres (conmutadores []), abiertos (booleano) | / | Configurar el interruptor de adquisición |
| /Profiler/Flame_Graph | CORREO | / | Ver Profilersampledto | Generar mapa de llama |
| /Profiler/Inicio | CORREO | / | Ver Profilersampledto, donde solo eventcounterinteval Field es válido | Ejecutar el comando de muestreo de inicio del perfiler |
| /Profiler/Stop | CORREO | / | Cadena, campo de formato en perfilers muestreado, el valor opcional es htmltxtjfr | Ejecutar el Profiler para finalizar el comando de archivo de muestreo y exportación |
| /Profiler/Estado | CONSEGUIR | / | / | Obtenga el estado actual del perfilador |
| /Profiler/list_events | CONSEGUIR | / | / | Obtenga los eventos de Profiler respaldados por el entorno actual |
| /perfiler/ejecutar | CORREO | / | comando (cadena) | Ejecutar el comando Profiler, ver Async-Profiler |
| /servidor/apagado | CONSEGUIR | objetivo (cadena) | / | Cerrar el servicio, los datos son el tipo de servicio |

La lógica operativa del modo Sentinel es recopilar regularmente elementos de datos especificados y luego empujarlos a los suscriptores . Debe proporcionar un servicio de suscripción (interfaz HTTP) que pueda recibir datos. Si el acceso a la interfaz requiere autenticación de identidad, la interfaz HTTP de suscriptor actualmente solo admite la autenticación básica .
Configuración del modo centinela
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
...Se admiten un total de los siguientes artículos de colección:
[
" 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 "
]Actualmente, solo los siguientes elementos de colección admiten 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 proporciona dos paneles de plantilla de Grafana, a saber: nodo y jvm
La plantilla de nodo es una colección de elementos de monitoreo relacionados con el sistema, que puede ayudarlo a concentrarse más en monitorear datos de máquinas físicas o hosts de nubes.


Método de importación: Importar ID de tablero de tablero 20430 o importar el nodo de panel de control.json
Para cooperar con esta plantilla, las siguientes tareas deben configurarse:
[
" process " ,
" disk_io " ,
" cpu " ,
" network " ,
" sys " ,
" sys_memory " ,
" sys_file "
]La plantilla JVM es una colección de elementos de monitoreo relacionados con JVM, que puede ayudarlo a centrarse más en los datos de monitoreo del proceso.


Método de importación: Importar ID del tablero 20429 o Importar Dashboard-JVM.JSON
Para cooperar con esta plantilla, las siguientes tareas deben configurarse:
[
" process " ,
" jvm_classloading " ,
" jvm_compilation " ,
" jvm_gc " ,
" jvm_memory " ,
" jvm_memory_pool " ,
" jvm_thread "
]Si desea desarrollar secundaria en función de JVMM, solo necesita introducir dependencias centrales
< dependency >
< groupId >io.github.tzfun.jvmm</ groupId >
< artifactId >jvmm-core</ artifactId >
< version >${jvmm-version}</ version >
</ dependency > Todas las interfaces funcionales de adquisición de datos proporcionadas por el servidor anterior y otras interfaces funcionales que no proporcionan interfaces de llamadas remotas se pueden obtener a través de una clase de fábrica: 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 ();
}
}La herramienta del cliente JVMM proporciona una forma simple y rápida de llamar a JVMM de forma remota. Por supuesto, también lleva a cabo funciones importantes, como el servidor adjunto y la generación de frascos de dependencia.
La herramienta Cliente proporciona una función de ejecución de comando Bootstrap, y se ejecutará una consulta incluso si no toma ningún parámetro. Para un uso específico, utilice el siguiente comando para ver el documento de ayuda:
java -jar jvmm.jar -hEjemplo de adquisición de datos por herramienta de cliente
Generar ejemplo de diagrama de llama

Ejemplo de llamada de código
Ejemplo de aplicación de tablero personalizado

Algunos componentes dentro del proyecto se pueden usar sin el proyecto, liviano y fácil de usar.
La razón es que su entorno no tiene herramientas JDK o variables de entorno no están configuradas. Asegúrese de que su entorno esté instalado con JDK en lugar de solo JRE. Verificación simple: ejecute jps -l en su entorno, y si se puede ejecutar normalmente y generar el resultado, significa que el entorno está bien.
Solución: Configure su directorio JDK bin local como una variable de entorno
Si comienza jvmm-server.jar, la razón es que está utilizando JDK 9 y más, Java prohíbe el acceso reflexivo a algunas clases que comienzan con 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
Solución: Agregue los siguientes parámetros de la máquina virtual
# 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 No access to perf events. Try --fdtransfer or --all-user option or 'sysctl kernel.perf_event_paranoid=1' , la razón es que el kernel del sistema prohíbe la detección del rendimiento del sistema de forma predeterminada, y debe habilitar esta opción.
sudo systcl -w kernel.perf_event_paranoid=1O modificar el archivo sysctl
sudo sh -c ' echo "kernel.perf_event_paranoid=1" >> /etc/sysctl.conf '
sudo sysctl -pEsta herramienta es completamente de código abierto y gratuita, y no es fácil de crear. Si cree que es bueno, puede donar para apoyar este proyecto.
Lista de donaciones:
Si encuentra algún problema durante el uso, o tiene información o sugerencias únicas sobre este proyecto, envíe un problema o envíeme un mensaje privado
Correo electrónico: [email protected]
WeChat: Beifeng-tz (tenga en cuenta JVMM si lo agrega)