btrace学习总结
btrace [-I <include-path>] [-p <port>] [-cp <classpath>] <pid> <btrace-script> [<args>]
?示例:?
btrace -cp common.jar 1200 AllCalls1.java
参数含义:?
include-path指定头文件的路径,用于脚本预处理功能,可选;?port指定BTrace agent的服务端监听端口号,用来监听clients,默认为2020,可选;?classpath用来指定类加载路径,默认为当前路径,可选;?pid表示进程号,可通过jps命令获取;?btrace-script即为BTrace脚本;btrace脚本如果以.java结尾,会先编译再提交执行。可使用btracec命令对脚本进行预编译。?args是BTrace脚本参数,在脚本中可通过"$"和"$length"获取参数信息,可选;?
1.获取方法参数值和返回值
import com.sun.btrace.annotations.*;import static com.sun.btrace.BTraceUtils.*;@BTracepublic class TracingScript { @OnMethod( clazz="com.learnworld.Counter", method="add", location=@Location(Kind.RETURN) ) public static void traceExecute(int num,@Return int result){ println("====== "); println(strcat("parameter num: ",str(num))); println(strcat("return value:",str(result))); }}
??
import com.sun.btrace.annotations.BTrace;import com.sun.btrace.annotations.OnMethod;import com.sun.btrace.annotations.Return;import com.sun.btrace.annotations.Self;import static com.sun.btrace.BTraceUtils.*;import com.sun.btrace.annotations.*;import com.taobao.eagleeye.model.RpcBased;@BTrace(unsafe=true) public class EgTest2 {@OnMethod(clazz="com.taobao.eagleeye.data.ip.IpAppMapper", method="getAppName",location=@Location(Kind.RETURN))public static void search(String ip,@Return String result){println(strcat(ip,result)); }}
?
2.定时获取Counter类的属性值totalCount。?
import com.sun.btrace.annotations.*;import static com.sun.btrace.BTraceUtils.*;@BTracepublic class TracingScript { private static Object totalCount = 0; @OnMethod( clazz="com.learnworld.Counter", method="add", location=@Location(Kind.RETURN) ) public static void traceExecute(@Self com.learnworld.Counter counter){ totalCount = get(field("com.learnworld.Counter","totalCount"), counter); } @OnTimer(1000) public static void print(){ println("====== "); println(strcat("totalCount: ",str(totalCount))); }}
?
?3. 获取add方法执行时间。
import com.sun.btrace.annotations.*;import static com.sun.btrace.BTraceUtils.*;@BTracepublic class TracingScript { @TLS private static long startTime = 0; @OnMethod( clazz="com.learnworld.Counter", method="add" ) public static void startExecute(){ startTime = timeNanos(); } @OnMethod( clazz="com.learnworld.Counter", method="add", location=@Location(Kind.RETURN) ) public static void endExecute(@Duration long duration){ long time = timeNanos() - startTime; println(strcat("execute time(nanos): ", str(time))); println(strcat("duration(nanos): ", str(duration))); } }
?
import com.sun.btrace.annotations.BTrace;import com.sun.btrace.annotations.OnMethod;import com.sun.btrace.annotations.Return;import com.sun.btrace.annotations.Self;import static com.sun.btrace.BTraceUtils.*;import com.sun.btrace.annotations.*;import org.apache.lucene.search.*;import org.apache.lucene.index.*;@BTracepublic class MultiTermQueryWrapperFilter { @TLS static long beginTime=0; @OnMethod(clazz="org.apache.lucene.search.MultiTermQueryWrapperFilter", method="getDocIdSet")public static void traceExecuteBegin(){ beginTime=timeMillis(); }@OnMethod(clazz="org.apache.lucene.search.MultiTermQueryWrapperFilter", method="getDocIdSet",location=@Location(Kind.RETURN))public static void mergeArray()throws Exception {println(strcat(strcat("MultiTermQueryWrapperFilter .execute time is:",str(timeMillis()-beginTime)),"ms"));}}
?
?
4. 获取add()方法调用方法sleep()次数。?
import com.sun.btrace.annotations.*;import static com.sun.btrace.BTraceUtils.*;@BTracepublic class TracingScript { private static long count; @OnMethod( clazz="/.*/", method="add", location=@Location(value=Kind.CALL, clazz="/.*/", method="sleep") ) public static void traceExecute(@ProbeClassName String pcm, @ProbeMethodName String pmn, @TargetInstance Object instance, @TargetMethodOrField String method){ println("====== "); println(strcat("ProbeClassName: ",pcm)); println(strcat("ProbeMethodName: ",pmn)); println(strcat("TargetInstance: ",str(classOf(instance)))); println(strcat("TargetMethodOrField : ",str(method))); count++; } @OnEvent public static void getCount(){ println(strcat("count: ", str(count))); }}
?
3. 获取参数的成员变量
@BTracepublic class OracleTimeoutTracer { @OnMethod(clazz = "oracle.net.nt.ConnStrategy", method = "createSocketOptions", location = @Location(value = Kind.ENTRY)) public static void strategy(@Self Object self, Properties paramProperties) { println(str(paramProperties)); } @OnMethod(clazz = "oracle.net.nt.TcpNTAdapter", method = "connect", location = @Location(value = Kind.ENTRY)) public static void adapter(@Self Object self) { Field socketTimeoutField = field("oracle.net.nt.TcpNTAdapter", "sockTimeout"); Field hostField = field("oracle.net.nt.TcpNTAdapter", "host"); Field portField = field("oracle.net.nt.TcpNTAdapter", "port"); int scoketTimeout = (Integer) get(socketTimeoutField, self); int port = (Integer) get(portField, self); String host = (String) get(hostField, self); println(strcat(strcat(strcat(strcat(strcat("host : ", host), ", port : "), str(port)), " , socketTimeout : "), str(scoketTimeout))); }}
?
import com.sun.btrace.annotations.BTrace;import com.sun.btrace.annotations.OnMethod;import com.sun.btrace.annotations.Return;import com.sun.btrace.annotations.Self;import static com.sun.btrace.BTraceUtils.*;import com.sun.btrace.annotations.*;import com.taobao.eagleeye.model.RpcBased;@BTrace(unsafe=true) public class EgTest1 {@OnMethod(clazz="com.taobao.eagleeye.digest.RealtimeDigester", method="generateStat")public static void search(RpcBased rpcBased){Object clientAppName = get(field("com.taobao.eagleeye.model.RpcBased","clientAppName"), rpcBased);Object serverAppName = get(field("com.taobao.eagleeye.model.RpcBased","serverAppName"), rpcBased);Object serviceId = get(field("com.taobao.eagleeye.model.RpcBased","serviceId"), rpcBased);Object host = get(field("com.taobao.eagleeye.model.RpcBased","host"), rpcBased);String a = strcat(str(clientAppName),",");String b = strcat(str(serverAppName),",");String c = strcat(str(serviceId),",");String e = strcat(str(host),",");String n1 = strcat(a,b);String n2 = strcat(c,e);println(strcat(n1,n2)); }}
?
?
?
1. btrace报错:Port 2020 unavailable
admin@eagleeyetlog128031 bin]$ ./btrace -cp eagleeye-common.jar 122810 EgTest1.java Port 2020 unavailable.
原因是btrace会在remote JVM(pid:122810)agent开启一个远程socketserver,默认端口是2020,正好我这台服务器有多个JVM实例,当我在第一个JVM上执行之后,第一个就会报错。正确的做法是:./btrace -cp eagleeye-common.jar -p 2021 53523 EgTest1.java 。
?
2. btrace报错:method calls are not allowed - only calls to BTraceUtils are allowed
原因是btrace存在安全限制,不允许调用被agent对象的方法。晚上说可以通过设计Dcom.sun.btrace.unsafe=true破解btrace的安全限制,但我试过不行。
?