基础准备
现在,我们需要一个程序入口,随时挂接具体的java应用和刚刚开发的agent。
首先,我们考虑java自身提供的功能:监控能力,主要包在 sun.jvmstat下,可以拿到当时正在运行的所有java进程,如此便可以让系统自动找到我们的测试java应用,避免每次去查看系统的进程号。
其次,我们考虑怎么动态的加载agent,目前来说最好的方式有两种,一个是自己引用tools.jar,使用类
com.sun.tools.attach.VirtualMachine加载,另外一种,就是借助第三方工具类,比如bytebuddy,目前我们先采用方式一,后面我们会详细讲解方式二。
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>jvm_sandbox_demo</artifactId><groupId>com.deer</groupId><version>1.0-SNAPSHOT</version><relativePath>../pom.xml</relativePath></parent><modelVersion>4.0.0</modelVersion><groupId>com.deer.agent.starter</groupId><artifactId>jvm_sandbox_agent_starter</artifactId><name>jvm_sandbox_agent_starter</name><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target></properties><dependencies><dependency><groupId>com.sun</groupId><artifactId>tools</artifactId><version>1.8</version><scope>system</scope><systemPath>/Users/yudongwei/Library/Java/JavaVirtualMachines/corretto-1.8.0_322/Contents/Home/lib/tools.jar</systemPath></dependency></dependencies></project>
package com.deer.agent.starter;import com.sun.tools.attach.VirtualMachine;import sun.jvmstat.monitor.*;import java.net.URISyntaxException;import java.util.HashSet;import java.util.Set;public class AgentStarter {public static void main(String[] args) throws URISyntaxException, MonitorException {String processId = null;// 获取监控主机MonitoredHost local = MonitoredHost.getMonitoredHost("localhost");// 取得所有在活动的虚拟机集合Set<Integer> vmlist = new HashSet<Integer>(local.activeVms());// 遍历集合,找到我们系统启动需要挂载的PID和进程名for(Integer process : vmlist) {MonitoredVm vm = local.getMonitoredVm(new VmIdentifier("//" + process));// 获取类名String processName = MonitoredVmUtil.mainClass(vm, true);if(processName.equals("com.deer.base.BaseApp")){processId = process.toString();break;}}if(processId == null){return;}System.out.println("find processId ,and ready to attach..."+processId);String agentPath="/Users/yudongwei/IdeaProjects/jvm_sandbox_demo/jvm_sandbox_agent/target/jvm_sandbox_agent-1.0-SNAPSHOT-jar-with-dependencies.jar";try {VirtualMachine vm = VirtualMachine.attach(processId);vm.loadAgent(agentPath);}catch (Exception e){e.printStackTrace();}}}
测试效果
启动 spring 应用:com.deer.base.BaseApp
打包agent
启动入口:com.deer.agent.starter.AgentStarter
基础测试
功能测试
我们用浏览器访问
http://localhost:9090/sayHi/zhangfei
新的问题
此时我们发现,自己定义的类有一个被agent访问到了(com.deer.base.service.BaseService),另外一个没有被agent访问到(com.deer.base.service.impl.HelloServiceImpl)
是我们代码写错了,还是另有玄机?
是不是因为spring的bean使用java代理,此时类名已经不匹配了?
这些都会随着接下来的课程一步一步抽丝剥茧解决。


