BTrace的最大好处,是可以通过自己编写的脚本,获取应用的一切调用信息。而不需要不断地修改代码,加入System.out.println(), 然后不断重启。
下载,https://github.com/btraceio/btrace。
解压后,把bin目录添加到环境变量。
这里先创建一个叫HelloWorld的类,然后用btrace监控它:
package com.tmg.helper;
import java.util.Random;
public class HelloWorld {
public static void main(String[] args) throws Exception {
//CaseObject object = new CaseObject();
while (true) {
Random random = new Random();
execute(random.nextInt(5000));
}
}
public static Integer execute(int sleepTime) {
try {
Thread.sleep(sleepTime);
} catch (Exception e) {}
System.out.println("sleep time is=>"+sleepTime);
return 0;
}
}
执行程序,每0-5秒,随机循环一次。可以使用jps得到pid。
btrace脚本:
import static com.sun.btrace.BTraceUtils.println;
import static com.sun.btrace.BTraceUtils.str;
import static com.sun.btrace.BTraceUtils.strcat;
import static com.sun.btrace.BTraceUtils.timeMillis;
import com.sun.btrace.annotations.BTrace;
import com.sun.btrace.annotations.Kind;
import com.sun.btrace.annotations.Location;
import com.sun.btrace.annotations.OnMethod;
import com.sun.btrace.annotations.ProbeClassName;
import com.sun.btrace.annotations.ProbeMethodName;
import com.sun.btrace.annotations.TLS;
@BTrace
public class TraceHelloWorld {
@TLS
private static long startTime = 0;
@OnMethod(clazz = "com.tmg.helper.HelloWorld", method = "execute")
public static void startMethod(){
startTime = timeMillis();
}
@OnMethod(clazz = "com.tmg.helper.HelloWorld", method = "execute", location = @Location(Kind.RETURN))
public static void endMethod(){
println(strcat("the class method execute time=>", str(timeMillis()-startTime)));
println("-------------------------------------------");
}
@OnMethod(clazz = "com.tmg.helper.HelloWorld", method = "execute", location = @Location(Kind.RETURN))
public static void traceExecute(@ProbeClassName String name,@ProbeMethodName String method,int sleepTime){
println(strcat("the class name=>", name));
println(strcat("the class method=>", method));
println(strcat("the class method params=>", str(sleepTime)));
}
}
这时在btrace脚本目录下执行btrace <pid> TraceHelloWorld.java
就可以监控HelloWorld.java。
如果还想监控其他内容,直接修改TraceHelloWorld.java,再执行一次btrace命令就可以了,不需要重启应用。结果输出到文件
./btrace -o mylog $pid HelloWorld.java
但首先,这个mylog会生成在应用的启动目录,而不是btrace的启动目录。其次,执行过一次-o之后,再执行btrace不加-o 也不会再输出回console,直到应用重启为止。所以推荐直接用转向:./btrace $pid HelloWorld.java > mylog
。
注意事项:
为了避免Btrace脚本的消耗过大影响真正业务,所以定义了一系列不允许的事情:比如不允许调用任何类的任何方法,只能调用BTraceUtils 里的一系列方法和脚本里定义的static方法。 比如不允许创建对象,比如不允许For 循环等等,可以用-u 运行在unsafe mode来规避限制,这个限制的开关设置在${BTRACE_HOME}/bin/btrace 脚本中com.sun.btrace.unsafe=true;
修改为false即可。 但不推荐。
BTrace植入过的代码,会一直在,直到应用重启为止。所以即使Btrace推出了,业务函数每次执行时都会多出一次Btrace是否Attach状态的判断。
参考:
http://blog.csdn.net/qyongkang/article/details/6091261
http://calvin1978.blogcn.com/articles/btrace1.html
http://jm.taobao.org/2010/11/11/509/
http://www.pigg.co/btrace-introduction.html