BTrace 是什麼java
BTrace 是檢查和解決線上的問題的殺器,BTrace 能夠經過編寫腳本的方式,獲取程序執行過程當中的一切信息,而且,注意了,不用重啓服務,是的,不用重啓服務。寫好腳本,直接用命令執行便可,不用動原程序的代碼。git
原理github
web
安裝和配置正則表達式
ubuntu
export JAVA_HOME=/home/fengzheng/soft/jdk1.8.0_111 export JRE_HOME=${JAVA_HOME}/jre export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib export PATH=${JAVA_HOME}/bin:$PATH export BTRACE_HOME=/home/fengzheng/soft/btrace export PATH=$PATH:$BTRACE_HOME/bin
api
簡單測試用例 數組
bash
微信
package kite.lab.utils; /** * NumberUtil * * @author fengzheng * @date 2017/2/15 */ public class NumberUtil { public int sum(){ int result = 0; for(int i = 0; i< 100; i++){ result += i * i; } return result; } public static void main(String[] args){ while (true) { Thread.currentThread().setName("計算"); NumberUtil util = new NumberUtil(); int result = util.sum(); System.out.println(result); try { Thread.sleep(5000); }catch (InterruptedException e){ } } } }
2. 執行上面的程序後,可用 jps
命令查看 pid(通常狀況下用哪一個帳號啓動的程序,就要用哪一個帳號執行 jps ,root 帳號除外),執行 jps 命令看到以下結果:
root@ubuntu:/home/fengzheng/codes/btrace# jps 10906 Jps 10860 NumberUtil
3. 能夠看到剛剛執行的 java 進程爲 10860
4. 編寫 btrace 腳本,腳本內容簡單以下:
package kite; import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.Strings.strcat; import static com.sun.btrace.BTraceUtils.jstack; import static com.sun.btrace.BTraceUtils.println; import static com.sun.btrace.BTraceUtils.str; /** * NumberUtilBTrace * * @author fengzheng * @date 2017/6/20 */ @BTrace public class NumberUtilBTrace { @OnMethod( clazz="kite.lab.utils.NumberUtil", method="sum", location=@Location(Kind.RETURN) ) public static void func(@Return int result) { println("trace: ======================="); println(strcat("result:", str(result))); jstack(); } }
意思是在執行結束後(location=@Location(Kind.RETURN) 表示執行結束)輸出結果和堆棧信息
trace: ======================= result:328350 kite.lab.utils.NumberUtil.sum(NumberUtil.java:16) kite.lab.utils.NumberUtil.main(NumberUtil.java:27)
7.
使用場景
好比哪些方法執行太慢,例如監控執行時間超過1s的方法
查看哪些方法調用了 System.gc() ,調用棧是怎樣的
查看方法參數或對象屬性
哪些方法發生了異常
多說一點,爲了更好解決問題,最好還要配合事前準備和進行中監控,事前準備就是埋點嘛,在一些可能出現問題的方法中進行日誌輸出,進行中監控就是利用一些實時監控工具,例如 VisualVM 、jmc 這些帶界面的工具或者 jdk 提供的命令行工具等,再高級一點的就是利用 Graphite 這樣的Metrics 工具配合 web 界面展現出來。
使用限制
BTrace class不能新建類, 新建數組, 拋異常, 捕獲異常,
不能調用實例方法以及靜態方法(com.sun.btrace.BTraceUtils除外)
不能將目標程序和對象賦值給BTrace的實例和靜態field
不能定義外部, 內部, 匿名, 本地類
不能有同步塊和方法
不能有循環
不能實現接口, 不能擴展類
不能使用assert語句, 不能使用class字面值
1. 精準定位
直接定位到一個類下的一個方法,上面測試用的例子就是
2. 正則表達式定位
正則表達式在兩個"/" 之間,例以下面的例子,監控 javax.swing 包下的全部方法,注意正式環境中,範圍儘量小一點,太大了性能會有影響。
@OnMethod(clazz="/javax\\.swing\\..*/", method="/.*/") public static void swingMethods( @ProbeClassName String probeClass, @ProbeMethodName String probeMethod) { print("entered " + probeClass + "." + probeMethod); }
經過在攔截函數的定義裏注入@ProbeClassName String probeClass, @ProbeMethodName String probeMethod 參數,告訴腳本實際匹配到的類和方法名。
3. 按接口或繼承類定位
@OnMethod(clazz="+com.kite.base", method="doSome")
4. 按註解定位
在前面加上 @ 便可,例如@OnMethod(clazz="@javax.jws.WebService", method="@javax.jws.WebMethod")
攔截時機由 location 決定,固然也可爲同一個定位加入多個攔截時機,便可以在進入方法時攔截、方法返回時攔截、拋出異常時攔截
1. Kind.Entry與Kind.Return
2. Kind.Error, Kind.Throw和 Kind.Catch
表示異常被 throw 、異常被捕獲還有異常發生可是沒有被捕獲的狀況,在攔截函數的參數定義裏注入一個Throwable的參數,表明異常
@OnMethod(clazz = "com.kite.demo", location = @Location(value = Kind.LINE, line = 20)) public static void onBind() { println("執行到第20行"); }
@OnMethod(clazz = "java.net.ServerSocket", method = "bind", location =@Location(Kind.ERROR)) public static void onBind(Throwable exception, @Duration long duration){ }
3. Kind.Call 和 Kind.Line
Kind.Call 表示被監控的方法調用了哪些其餘方法,例如:
@OnMethod(clazz = "com.kite", method = "login", location = @Location(value = Kind.CALL, clazz = "/.*/", method = "/.*/", where = Where.AFTER)) public static void onBind(@Self Object self, @TargetInstance Object instance, @TargetMethodOrField String method, @Duration long duration){ println(strcat("self: ", str(self))); println(strcat("instance: ", str(instance))); println(strcat("method: ", str(method))); println(strcat("duration(ms): ", str(duration / 1000000))); }
Kind.Line 監測類是否執行到了設置的行數,例如:
@OnMethod(clazz = "com.kite.demo", location = @Location(value = Kind.LINE, line = 20)) public static void onBind() { println("執行到第20行"); }
@OnMethod(clazz = "java.lang.System", method = "gc") public static void onSystemGC() { println("entered System.gc()"); jstack(); }
@OnMethod(clazz = "/com\\.kite\\.controller\\..*/",method = "/.*/",location = @Location(Kind.RETURN)) public static void slowQuery(@ProbeClassName String pcn,@ProbeMethodName String probeMethod, @Duration long duration){ if(duration > 1000000 * 100){ println(strcat("類:", pcn)); println(strcat("方法:", probeMethod)); println(strcat("時長:", str(duration / 1000000))); } }
古時的風箏 【微信公衆號】gushidefengzheng