jip 和 btrace 是两个著名的开源工具,它们都可以察看另一个jvm进程的信息:jip的客户进程可以打印另一个进程中每个方法的执行时间,btrace则可以直接查看甚至改变变量的值。
两个工具可以做的事都直接依赖java instrument api。通过这个api在目标进程运行时修改字节码,在一定程度上改变代码的执行:jip让目标进程给出执行时间,btrace让目标进程给出变量的值。
jip和btrace在执行时都有自己的进程。它们自己的进程接收目标进程释放的信息,然后展现出来。
现在的问题是,工具自己的进程是怎么样跟目标进程通信的?
经研究发现:
1.
jip进程与目标进程是通过原生的socket进行通信的。目标进程在启动时须使用-javaagent
jip-xxx.jar这个jvm参数(java instrument的“Command-Line Interface”)立即进行字节码instrument操作。具体的操作中包含一步:启动一个ServerSocket. jip进程启动后再访问这个ServerSocket.
2.
btrace进程与目标进程则是通过java attach api进行通信的。通过指定一个进程号,btrace进程可以拿到目标进程的句柄。这个句柄是VirtualMachine类的实例,而这个类有一个方法叫loadAgent(),通过这个方法,btrace进程再把预先准备好的agent注入到目标进程实现字节码的动态修改(java instrument的"Starting Agents After VM Startup"模式)
优劣性比较
假设目标进程是java web应用,两者的优劣点可以从多个方面来比较。
1.
运行时的侵入性:btrace优于jip. jip需要在启动目标进程时就使用-javaagent参数,这可能导致贵公司服务器的启动脚本的改动。你们的运维人员未必愿意帮忙。
2.
能否instrument远程的进程:jip优于btrace,因为btrace所基于的java attach api只能捆绑本机的进程,而jip基于的socket没有这个限制。
3.
实现的简易性:btrace优于jip. 使用现成的attach api,当然比手工实现一套基于socket的c/s模型要省事。
4.
平台无关性: jip胜出,因为btrace基于的attach api有两大制约:
a. java6 以后才有这个api
b. 这个api本身没有javax.*或java.*的接口;相反hotspot使用了com.sun.*作为包名,IBM jdk则使用了com.ibm.*作为包名,其它的jdk则未必实现了attach api规范。