一个监控 jvm 信息的 springboot 学习的 demo 项目。
- 监控 jvm 系统信息、类加载状态、线程状态、内存使用状态等。
- 分析出 cpu 热点 (cpu profiler)
- 在代码运行时动态查看方法执行耗时、堆栈、入参和返回值
- java agent、jmx、attach api、Byte Buddy、SpringBoot
- 监控 jvm 信息
- 通过 VirtualMachine.list() 获取本地 jvm 列表,主要是 pid 和 name
- 选择需要监控的 jvm,通过 pid 和该 jvm 建立连接,此 springboot 项目作为一个 jmx 客户端
- 通过建立的连接获取各种 MXBean 的信息。
- cpu profiler
通过定时任务 dump 线程堆栈信息,然后统计汇总。
- 动态查看方法执行耗时、堆栈、入参和返回值
- 定义 agentmain 方法,通过使用 java attach api 可以动态加载 agent 到 jvm 中
- 使用 Byte Buddy AgentBuilder 类开发 agent
- 开发执行耗时、堆栈、入参和返回值对应的 Advice
该项目分为 2 个分支:agent、monitor
- agent 实现 java agent,查看运行时方法执行耗时、堆栈、入参和返回值。
- monitor 是 springBoot 程序,提供交互接口。
- 将 agent 项目打包,将打成的 jar 包路径放在 monitor 项目中 application.properites 中。
- 启动 monitor 项目,调用 JvmController 中 getJVMList 接口
- 选择感兴趣的 jvm 程序,此处选择当前启动的 springBoot 程序,将该 pid 作为参数,调用 JvmController 中 attach 接口,建立与 jmx 的连接。
- 调用 DashboardController 中的 getOperatingSystemInfo 接口获取操作信息信息。其他 jvm 信息也是调用 DashboardController 的接口。
- 调用 AgentController 的 agent 接口,请求参数如下图
function 表示拦截的功能,方法耗时对应 time,方法堆栈对应 trace,方法入参和返回值对应 params; className 表示需要拦截类的全类名; methodName 表示需要拦截的方法名;
上面请求就是拦截 DashboardService 类的 getMemoryInfo 方法,获取方法入参和返回值。
- 调用 DashboardController 类的 heapMemoryInfo 方法,查看拦截打印的内容:
agent params method : public org.monitor.entity.info.MemoryInfo org.monitor.service.DashboardService.getMemoryInfo(int) enter params are : [1]
agent params method : public org.monitor.entity.info.MemoryInfo org.monitor.service.DashboardService.getMemoryInfo(int) return params are : MemoryInfo(init=268435456, used=183800936, committed=359137280, max=3817865216)
- cpuProfiler 功能需要调用 ProfilerController 的 startCpuProfiler 接口开始进行统计,一段时间后最后调用 endCpuProfiler 接口结束统计。
- cpu profiler 参考:https://github.com/uber-common/jvm-profiler
- 支持连接远程 jvm 进程。