Btrace用于调试正在运行的系统,并且在调试时不会暂停系统。特别适用于跟踪线上问题。你可以实时监控一个系统中任何一个方法的调用,你可以知道这些方法的参数、返回值是什么,还可以知道方法调用消耗了多少时间。
Btrace不需要安装,只要下载一个包,解压即可。
Btrace用法为bin/btrace <pid> <trace-script>。其中pid是正在运行的java进程,trace-script是跟踪脚本,它其实就是一段java代码。
首先我们模拟一个正在运行的程序,它仅有一个循环。
}
然后开启这个程序: java com.caipeichao.NullApp
通过jps命令得到这个程序的PID,这里为13348。
> jps3034 RemoteMavenServer2902 Main15147 Jps13348 NullApp
准备工作做完了,现在编写最重要的跟踪脚本。
@BTrace}
运行btrace,得到如下输出。
> btrace 13348 HelloBtrace.javaHello worldHello worldHello worldHello worldHello worldHello world
| 名称 | 作用域 | 作用 | 
|---|---|---|
| @BTrace | 类 | 声明跟踪脚本 | 
| @OnMethod(clazz,method,location) | 方法 | 当指定方法被调用时 | 
| @OnMethod(method="<init>") | 方法 | 当构造函数被调用时 | 
| @OnMethod(clazz="/java\\.io\\..*Input/")) | 方法 | 方法名称正则匹配 | 
| @Location(kind) | @OnMethod | 指定监控方法调用前还是调用后 | 
| @Location(value=Kind.NEWARRAY, clazz="char") | @OnMethod | 监控新增数组 | 
| @Self | 参数 | 表示被监控的对象 | 
| @ProbeMethodName | 参数 | 被监控的方法名称 | 
| @ProbeClassName | 参数 | 被监控的类名 | 
| @OnTimer(interval) | 方法 | 定时调用某个方法 | 
| @OnLowMemory(pool,threshold) | 方法 | 当内存不足时 | 
| @OnExit | 方法 | 当程序退出时 | 
| @OnProbe(namespace="java.net.socket",name="bind") | 方法 | 监控socket中的bind方法 | 
| 方法 | 作用 | 
|---|---|
| println | 在本地控制台输出一行 | 
| print | 在本地控制台输出 | 
| printArray | 在本地控制台输出数组 | 
| jstack | 打印远程方法的调用调用栈 | 
| jstackAll | 输出所有线程的调用栈 | 
| exit | 退出跟踪脚本 | 
| Strings.strcat | 连接字符串 | 
| Reflactive.name | 获取类名 | 
| Threads.name | 线程名 | 
| Threads.currentThread | 当前线程 | 
| deadlocks | 打出死锁线程 | 
| sizeof | 获取对象的大小,比如 List对象就返回List.size() | 
| Sys.Env.property | 获取系统变量 | 
BTrace利用了java.lang.instrument包实现代码注入。首先通过VirtualMachine.attach(pid)连接远程JVM,然后通过VirtualMachine.loadAgent("*.jar")加载一个btrace的jar包。这个jar包最重要的代码如下。
public static void {;}public static void {;}// 将btrace的jar包添加到ClassLoader搜索目录private static synchronized void {...inst.;...inst.;...;}// 开启服务private static void {...while (true) {try {...;} catch (RuntimeException re) {if () ;} catch (IOException ioexp) {if () ;}}}// 修改内存中的类定义private static void {...inst.;...inst.;}// 用ASM动态生成字节码}
一句话总结,btrace利用instrument工具修改JVM内存中的类字节码,达到注入代码的目的。
原文地址:http://blog.csdn.net/caipeichao2/article/details/42109429