上一次分享中有一个疑问,就是目标jvm进程和代理程序,也就是卧底程序是一起运行的.还记得吗? 通过使用如下命令:
java -javaagent:jar 文件的位置 [= 传入 premain 的参数 ]
这个势必会造成一个困惑,就是如果目标jvm进程已经先开始运行了,难不成卧底就监控不了了吗?这就好比一个小偷要去人家偷东西,难不成房子还没竣工,小偷就要去蹲点吗, 这显然是不合理的。 jdk的开发团队也意识到了这个问题, 于是他们对jdk做了以下优化,提供了agentmain函数:(之前那个函数叫premain函数)
这个函数同样有两个重载的方法:
public static void agentmain (String agentArgs, Instrumentation inst); [1]
public static void agentmain (String agentArgs);
乍看起来和premain 函数很相似,其他使用基本相同,但是agent jar包里面的manifest文件的
key值改为Agent-Class
Manifest-Version: 1.0
Premain-Class: com.sun.btrace.agent.Main
Agent-Class: com.sun.btrace.agent.Main
不知道大家有没有注意到,如果采用后一种方法(agentmain 方式),这个函数是如何触发的呢, 人家premain函数好歹是和目标jvm进程一起启动的,
但是agentmain函数的运行时机是什么呢?
这就用到了Attach API.
Attach Api 家族的成员非常的少。 我们这里只关注2个类,”VirtualMachine” and “AttachProvider”
AttachProvider 的实现是针对不同的操作来使用的。 也就是说,如果你在windows上
你需要使用WindowsAttachProvider,在Maco上要使用MacosxAttachProvider ,使用linux 就要使用 LinuxAttachProvider 。
正如他的名字提到的, AttachProvider针对每种不同的操作系统提供(provide)一个可以访问的 VirtualMachine的示例,
接下来咱们代码说话看看如何使用AttachAPI
- VirtualMachine代表着一个jvm进程, 那么首先我得知道有这么个进程啊, 所以通过prstate(sloris) top(linux)等工具去查询jvm进程有哪些,选择你想要监控的进程, 通常你还可以使用ps aux 命令, 如果上面的命令你还是不清楚。 你也可以使用jdk 自带的工具jps, 这里会列表所有的java 进程。jps工具各种平台通用啊。 知道javac 和java 放在那儿吧。 他们都是一个路径下面的亲戚
- 既然VirtualMachine代表着一个jvm进程,那我们得想办法让这个类的实例和一个进程进行绑定吧。 好在这个类提供的这个方法,看下面的代码
VirtualMachine vm = VirtualMachine.attach("18244");
try {
vm.loadAgent("/../agent.jar");
// System.out.println(vm.getAgentProperties().get("XXX"));
} finally {
vm.detach();
}
第一行已经提示, 这里采用attach方法和一个进程进行绑定。 那个数字18244 就是咱们在第一部列出的进程号
接着,如果你想安插一个agent程序进行监控18244进程程序, 采用loadAgent方法。 这个agent怎么写, 我刚才已经提到过了。最后注意要释放这个进程,当监控工作完毕之后
看到这段代码,我们貌似并没有用到AttachProvider啊, 其实当我们调用VirtualMachine.attach方法的时候,他其实已经用到了AttachProvider了哦
// VirtualMachine vm = VirtualMachine.attach("pid");
VirtualMachine vm = null;
List providers = AttachProvider.providers();
for (AttachProvider provider : providers) {
try {
vm = provider.attachVirtualMachine("pid");
break;
} catch (Exception e) {
// do sth. necessary
continue;
}
}
通过上面的代码自动的匹配平台,所以咱们就不用关心不同的操作系统选择不同类型AttachProvider了。
instrument 和AttachAPI 都是Btrace源码的学习基础, 此外还是各种监控工具的原理基础哦。
大家可以看一下btrace 的agent jar 包,里面的manifest配置,恰好说明了这一点哦
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.8.0
Created-By: 1.7.0_40-b43 (Oracle Corporation)
Premain-Class: com.sun.btrace.agent.Main
Agent-Class: com.sun.btrace.agent.Main
杏树林研发 韩健