CONAN ZONE

          你越掙扎我就越興奮

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            0 Posts :: 282 Stories :: 0 Comments :: 0 Trackbacks

           BTrace(https://btrace.dev.java.net/) 是一個非常不錯的java診斷工具, 最近試著用了一下, 文檔比較少, 主要是看例子吧. 
          BTrace 中的B表示bytecode, 表明它是在字節碼層面上對代碼進行trace 
          用來在運行中的java類中注入trace代碼, 并對運行中的目標程序進行熱交換(hotswap) 

          btrace還提供了VisualVM Plugin 以及Netbeans Plugin

          術語 
          Probe Point 
          在何處執行trace語句, 這里的"何處"可以是具體的跟蹤地點和執行事件, BTrace中通過各種注解來指定 

          Trace Actions or Actions 
          在何時執行trace語句 

          Action Methods 
          定義在trace腳本中的trace語句, 具體來說就是腳本中的無返回值靜態方法(1.2之后可以是非靜態方法) 

          BTrace限制 
          為了保證trace語句只讀, BTracetrace腳本有一些限制(比如不能改變被trace代碼中的狀態) 

          ·         BTrace class不能新建類, 新建數組, 拋異常, 捕獲異常,

          ·         不能調用實例方法以及靜態方法(com.sun.btrace.BTraceUtils除外)

          ·         不能將目標程序和對象賦值給BTrace的實例和靜態field

          ·         不能定義外部, 內部, 匿名, 本地類

          ·         不能有同步塊和方法

          ·         不能有循環

          ·         不能實現接口, 不能擴展類

          ·         不能使用assert語句, 不能使用class字面值

          BTrace步驟 
          1.取得目標java進程id(pid) 
          2.編寫BTrace腳本 
          3.執行命令行:  
          btrace <pid> <自己定制的腳本> <輸出文件>

          eg:btrace 3045PrintExecuteTime.java > time.log 

          完整的BTrace命令: 

          引用
          btrace [-I <include-path>] [-p <port>] [-cp <classpath>] <pid> <btrace-script> [<args>]

           

          • -I 沒有這個表明跳過預編譯
          • include-path: 指定用來編譯腳本的頭文件路徑(關于預編譯可參考例子ThreadBean.java)
          • port : btrace agent端口, 默認是2020
          • classpath : 編譯所需類路徑, 一般是指btrace-client.jar等類所在路徑
          • pid : java進程id
          • btrace-script: btrace腳本, 如果是java文件, 則是未編譯, class文件, 則是已編譯過的
          • args: 傳遞給btrace腳本的參數, 在腳本中可以通過$(), $length()來獲取這些參數(定義在BTraceUtils中)

          預編譯BTrace腳本命令 

          引用
          btracec [-I <include-path>] [-cp <classpath>] [-d <directory>] <one-or-more-BTrace-.java-files>


          參數和上面大同小異, btracec 是一個類似javac的程序, 使用該程序編譯, 將根據BTrace的限制條件進行嚴格檢查 

          在目標程序中啟動BTrace Agent 
          這個主要針對需要在目標程序啟動的時候就需要trace其行為的場景, 此時BTrace agent將與目標程序一起啟動(前提是必須對BTrace腳本進行預編譯) 
          命令行: 

          引用
          java -javaagent:btrace-agent.jar=script=<pre-compiled-btrace-script1>[,<pre-compiled-btrace-script1>]* <MainClass> <AppArguments>

          方法上的注解 

          • @com.sun.btrace.annotations.OnMethod  用來指定trace的目標類和方法以及具體位置, 被注解的方法在匹配的方法執行到指定的位置會被調用. "clazz"屬性用來指定目標類名, 可以指定全限定類名, 比如"java.awt.Component", 也可以是正則表達式(表達式必須寫在"http://"中, 比如"/java\\.awt\\..+/").  "method"屬性用來指定被trace的方法. 表達式可以參考自帶的例子(NewComponent.java 和 Classload.java, 關于方法的注解可以參考MultiClass.java). 有時候被trace的類和方法可能也使用了注解. 用法參考自帶例子WebServiceTracker.java. 針對注解也是可以使用正則表達式, 比如像這個"@/com\\.acme\\..+/ ", 也可以通過指定超類來匹配多個類, 比如"+java.lang.Runnable"可以匹配所有實現了java.lang.Runnable接口的類. 具體參考自帶例子SubtypeTracer.java.
          • @com.sun.btrace.annotations.OnTimer 用來指定時長(ms)執行一次trace. 時長通過"value"屬性指定. 具體參考自帶例子 Histogram.java
          • @com.sun.btrace.annotations.OnError 當trace代碼拋異常時該注解的方法會被執行. 如果同一個trace腳本中其他方法拋異常, 該注解方法也會被執行.
          • @com.sun.btrace.annotations.OnExit 當trace方法調用內置exit(int)方法(用來結束整個trace程序)時, 該注解的方法會被執行. 參考自帶例子ProbeExit.java.
          • @com.sun.btrace.annotations.OnEvent 用來截獲"外部"btrace client觸發的事件, 比如按Ctrl-C 中斷btrace執行時將執行使用了該注解的方法, 該注解的value值為具體事件名稱. 具體參考例子HistoOnEvent.java
          • @com.sun.btrace.annotations.OnLowMemory 當內存超過某個設定值將觸發該注解的方法, 具體參考MemAlerter.java
          • @com.sun.btrace.annotations.OnProbe //我也沒搞明白:(

          參數上的注解 

          • @com.sun.btrace.annotations.Self 用來指定被trace方法的this, 可參考例子AWTEventTracer.java 和 AllCalls1.java
          • @com.sun.btrace.annotations.Return 用來指定被trace方法的返回值, 可參考例子Classload.java
          • @com.sun.btrace.annotations.ProbeClassName (since 1.1) 用來指定被trace的類名, 可參考例子AllMethods.java
          • @com.sun.btrace.annotations.ProbeMethodName (since 1.1) 用來指定被trace的方法名, 可參考例子WebServiceTracker.java
          •           o (since 1.2)可以通過注解的fqn boolean屬性來表明是否要獲取全限定方法名 
          • @com.sun.btrace.annotations.TargetInstance (since 1.1) 用來指定被trace方法內部被調用到的實例, 可參考例子AllCalls2.java
          • @com.sun.btrace.annotations.TargetMethodOrField (since 1.1) 用來指定被trace方法內部被調用的方法名, 可參考例子AllCalls1.java 合 AllCalls2.java
          •           o (since 1.2) 可通過注解的fqn boolean屬性來表明是否要獲取全限定方法名 

          未被注解的方法參數 
          未使用注解的方法參數一般都是用來做方法簽名匹配用的, 他們一般和被trace方法中參數出現的順序一致. 不過他們也可以與注解方法交錯使用, 如果一個參數類型聲明為*AnyType[]*, 則表明它按順序"通吃"方法所有參數. 未注解方法需要與*Location*結合使用: 

          • Kind.ENTRY, Kind.RETURN- 被trace方法參數
          • Kind.THROW - 拋異常
          • Kind.ARRAY_SET, Kind.ARRAY_GET - 數組索引
          • Kind.CATCH - 捕獲異常
          • Kind.FIELD_SET - 屬性值
          • Kind.LINE - 行號
          • Kind.NEW - 類名
          • Kind.ERROR - 拋異常

          屬性上的注解 

          • @com.sun.btrace.annotations.Export 該注解的靜態屬性主要用來與jvmstat計數器做關聯. 使用該注解之后, btrace程序就可以向jvmstat客戶端(可以用來統計jvm堆中的內存使用量)暴露trace程序的執行次數, 具體可參考例子ThreadCounter.java
          • @com.sun.btrace.annotations.Property 使用了該注解的trace腳本將作為MBean的一個屬性, 一旦使用該注解, trace腳本就會創建一個MBean并向MBean服務器注冊, 這樣JMX客戶端比如VisualVM, jconsole就可以看到這些BTrace MBean. 如果這些被注解的屬性與被trace程序的屬性關聯, 那么就可以通過VisualVM 和jconsole來查看這些屬性了. 具體可參考例子ThreadCounterBean.java 和 HistogramBean.java.
          • @com.sun.btrace.annotations.TLS 用來將一個腳本變量與一個ThreadLocal變量關聯. 因為ThreadLocal變量是跟線程相關的, 一般用來檢查在同一個線程調用中是否執行到了被trace的方法. 具體可參考例子OnThrow.java 和 WebServiceTracker.java

          類上的注解 

          • @com.sun.btrace.annotations.DTrace 用來指定btrace腳本與內置在其腳本中的D語言腳本關聯, 具體參考例子DTraceInline.java.
          • @com.sun.btrace.annotations.DTraceRef 用來指定btrace腳本與另一個D語言腳本文件關聯. 具體參考例子DTraceRefDemo.java.
          • @com.sun.btrace.annotations.BTrace 用來指定該java類為一個btrace腳本文件.



          監控方法參數(數組)

           1     import static com.sun.btrace.BTraceUtils.print;    
           2     import static com.sun.btrace.BTraceUtils.printArray;    
           3     import static com.sun.btrace.BTraceUtils.println;    
           4     import static com.sun.btrace.BTraceUtils.probeClass;    
           5     import static com.sun.btrace.BTraceUtils.probeMethod;    
           6        
           7     import com.sun.btrace.annotations.BTrace;    
           8     import com.sun.btrace.annotations.OnMethod;    
           9        
          10     @BTrace   
          11     public class PrintArgArray {    
          12        
          13         /** 
          14           * 此方法打印出Test類中的mergeArray(Long[] arrayOne, Long[] arrayTwo)方法傳入的參數 
          15           * 參數名字一定要和監控對象的方法參數名字一致 
          16           * 
          17           * @param arrayOne 監控參數一 
          18           * @param arrayTwo 監控參數二 
          19           * @author jerry 
          20           */   
          21         @OnMethod(clazz = "com.jerry.test.Test", method = "mergeArray")    
          22         // 此處寫明要監控的包、類、方法等   可以使用正則匹配    
          23         public static void anyRead(Long[] arrayOne, Long[] arrayTwo) {    
          24             // 打印監控的類名    
          25              print(probeClass());    
          26              print("   [");    
          27             // 打印監控的方法名    
          28              print(probeMethod());    
          29              println("]");    
          30        
          31             if (arrayOne != null) {    
          32                  printArray(arrayOne);    
          33              } else {    
          34                  println("the arguments is null!");    
          35              }    
          36        
          37             if (arrayTwo != null) {    
          38                  printArray(arrayTwo);    
          39              } else {    
          40                  println("the arguments is null!");    
          41              }    
          42          }    
          43        
          44     }   


          監控使用時間

           1     import static com.sun.btrace.BTraceUtils.name;    
           2     import static com.sun.btrace.BTraceUtils.print;    
           3     import static com.sun.btrace.BTraceUtils.println;    
           4     import static com.sun.btrace.BTraceUtils.probeClass;    
           5     import static com.sun.btrace.BTraceUtils.probeMethod;    
           6     import static com.sun.btrace.BTraceUtils.str;    
           7     import static com.sun.btrace.BTraceUtils.strcat;    
           8     import static com.sun.btrace.BTraceUtils.timeMillis;    
           9        
          10     import com.sun.btrace.annotations.BTrace;    
          11     import com.sun.btrace.annotations.Kind;    
          12     import com.sun.btrace.annotations.Location;    
          13     import com.sun.btrace.annotations.OnMethod;    
          14     import com.sun.btrace.annotations.TLS;    
          15        
          16     /** 
          17     * 監控方法耗時 
          18     * 
          19     * @author jerry 
          20     */   
          21     @BTrace   
          22     public class PrintTimes {    
          23        
          24         /** 
          25           * 開始時間 
          26           */   
          27         @TLS   
          28         private static long startTime = 0;    
          29        
          30         /** 
          31           * 方法開始時調用 
          32           */   
          33         @OnMethod(clazz = "/com\\.jerry\\../", method = "/.+/")    
          34         public static void startMethod() {    
          35              startTime = timeMillis();    
          36          }    
          37        
          38         /** 
          39           * 方法結束時調用<br> 
          40           * Kind.RETURN這個注解很重要 
          41           */   
          42         @SuppressWarnings("deprecation")    
          43         @OnMethod(clazz = "/com\\.jerry\\../", method = "/.+/", location = @Location(Kind.RETURN))    
          44         public static void endMethod() {    
          45        
          46              print(strcat(strcat(name(probeClass()), "."), probeMethod()));    
          47              print("   [");    
          48              print(strcat("Time taken : ", str(timeMillis() - startTime)));    
          49              println("]");    
          50          }    
          51     }   


          監控內存

           1     import static com.sun.btrace.BTraceUtils.*;    
           2     import java.lang.management.MemoryUsage;    
           3        
           4     import com.sun.btrace.annotations.BTrace;    
           5     import com.sun.btrace.annotations.OnLowMemory;    
           6        
           7     /** 
           8     * 監控內存使用 
           9     * 
          10     * @author jerry 
          11     */   
          12     @BTrace   
          13     public class PrintMemory {    
          14        
          15         /* 
          16           * 指定內存區域低于一定的界限的時候才內存使用打印數據<br> 也可以指定時間間隔打印內存使用 
          17           */   
          18         @OnLowMemory(pool = "Tenured Gen", threshold = 6000000)    
          19         public static void printMem(MemoryUsage mu) {    
          20              print("MemoryUsage : ");    
          21              println(mu);    
          22              print("FreeMem : ");    
          23              println(freeMemory());    
          24              print("Heap:");    
          25              println(heapUsage());    
          26              print("Non-Heap:");    
          27              println(nonHeapUsage());    
          28          }    
          29     }   











           

          posted on 2011-12-08 22:03 CONAN 閱讀(1924) 評論(0)  編輯  收藏 所屬分類: JAVA
          主站蜘蛛池模板: 北碚区| 梁山县| 义马市| 普洱| 曲靖市| 沅江市| 无极县| 江永县| 蒙阴县| 鄂温| 沙河市| 青田县| 长乐市| 大方县| 保山市| 英德市| 三台县| 平江县| 星子县| 化德县| 蒲城县| 新竹县| 会东县| 长泰县| 循化| 乌兰县| 宾阳县| 卓资县| 陕西省| 确山县| 新竹市| 金华市| 南雄市| 河北区| 博罗县| 太白县| 耿马| 涿鹿县| 睢宁县| 孟津县| 安陆市|