btrace 用戶手冊

btrace 文件中的一些參數配置 可以修改,比如 classpath(默認沒有,需要自己配置)

${JAVA_HOME}/bin/java -Dcom.sun.btrace.bootClassPath=/usr/tmp/build  -Dcom.sun.btrace.probeDescPath=. -Dcom.sun.btrace.dumpClasses=false -Dcom.sun.btrace.debug=true -Dcom.sun.btrace.unsafe=true -cp ${BTRACE_HOME}/build/btrace-client.jar:${TOOLS_JAR}:/usr/share/lib/java/dtrace.jar com.sun.btrace.client.Main $*





BTrace 中的B表示bytecode, 表明它是在字節碼層面上對代碼進行trace

用來在運行中的java類中注入trace代碼, 並對運行中的目標程序進行熱交換(hotswap)

術語
Probe Point

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

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

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

BTrace限制
爲了保證trace語句只讀, BTrace對trace腳本有一些限制(比如不能改變被trace代碼中的狀態)
  • BTrace class不能新建類, 新建數組, 拋異常, 捕獲異常,
  • 不能調用實例方法以及靜態方法(com.sun.btrace.BTraceUtils除外)
  • 不能將目標程序和對象賦值給BTrace的實例和靜態field
  • 不能定義外部, 內部, 匿名, 本地類
  • 不能有同步塊和方法
  • 不能有循環
  • 不能實現接口, 不能擴展類
  • 不能使用assert語句, 不能使用class字面值


BTrace例子
Java代碼  收藏代碼
  1. // import all BTrace annotations  
  2. import com.sun.btrace.annotations.*;  
  3. // import statics from BTraceUtils class  
  4. import static com.sun.btrace.BTraceUtils.*;  
  5.    
  6. // @BTrace annotation tells that this is a BTrace program  
  7. @BTrace  
  8. class HelloWorld {  
  9.     
  10.     // @OnMethod annotation tells where to probe.  
  11.     // In this example, we are interested in entry  
  12.     // into the Thread.start() method.  
  13.     @OnMethod(  
  14.         clazz="java.lang.Thread",  
  15.         method="start"  
  16.     )  
  17.     void func() {  
  18.         sharedMethod(msg);  
  19.     }  
  20.    
  21.    void sharedMethod(String msg) {  
  22.         // println is defined in BTraceUtils  
  23.         println(msg);  
  24.    }  
  25. }  


BTrace步驟
1.取得目標java進程id(pid)
2.編寫BTrace腳本
3.執行命令行: btrace <pid> <btrace-script>

完整的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>


還有個btracer 腳本. //不過沒看明白
引用
btracer <pre-compiled-btrace.class> <application-main-class> <application-args>


一些支持的參數:
  • bootClassPath - 啓動classpath
  • systemClassPath - 系統classpath
  • debug - 是否打開調試信息(true/false)
  • unsafe - 是否開啓btrace限制約束(true/false) // 我設置爲true貌似無效
  • dumpClasses - 是否dump被trace的目標二進制代碼 (true/false)
  • dumpDir - 指定dump文件路徑
  • stdout - 是否重定向btrace輸出到標準輸出(true/false)
  • probeDescPath - 指定trace點的描述 XML文件路徑
  • script - 指定btrace agent啓動時的運行的腳本
  • scriptdir - 指定btrace agent啓動時要運行的腳本所在文件夾
  • scriptOutputFile - btrace agent輸出文件代理地址


方法上的註解
  • @com.sun.btrace.annotations.OnMethod  用來指定trace的目標類和方法以及具體位置, 被註解的方法在匹配的方法執行到指定的位置會被調用. "clazz"屬性用來指定目標類名, 可以指定全限定類名, 比如"java.awt.Component", 也可以是正則表達式(表達式必須寫在"//"中, 比如"/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腳本文件.


DTrace 集成(略過)

相關例子一句話說明

  • AWTEventTracer.java - 演示了對EventQueue.dispatchEvent()事件進行trace的做法, 可以通過instanceof來對事件進行過濾, 比如這裏只針對focus事件trace.
  • AllLines.java - 演示瞭如何在被trace的程序到達probe指定的類和指定的行號時執行指定的操作(例子中指定的行號是-1表示任意行).
  • AllSync.java - 演示瞭如何在進入/退出同步塊進行trace.
  • ArgArray.java - 演示了打印java.io包下所有類的readXXX方法的輸入參數.
  • Classload.java - 演示打印成功加載指定類以及堆棧信息.
  • CommandArg.java - 演示如何獲取btrace命令行參數.
  • Deadlock.java - 演示了@OnTimer註解和內置deadlock()方法的用法
  • DTraceInline.java - 演示@DTrace註解的用法
  • DTraceDemoRef.java - 演示@DTraceRef 註解的用法.
  • FileTracker.java - 演示瞭如何對File{Input/Output}Stream構造函數中初始化打開文件的讀寫文件操作進行trace.
  • FinalizeTracker.java - 演示瞭如何打印一個類所有的屬性, 這個在調試和故障分析中非常有用. 這裏的例子是打印FileInputStream類的close() /finalize() 方法被調用時的信息.
  • Histogram.java - 演示了統計javax.swing.JComponent在一個應用中被創建了多少次.
  • HistogramBean.java - 同上例, 只不過演示瞭如何與JMX集成, 這裏的map屬性通過使用@Property註解被暴露成一個MBean.
  • HistoOnEvent.java - 同上例, 只不過演示瞭如何在通過按ctrl+c中斷當前腳本時打印出創建次數, 而不是定時打印.
  • JdbcQueries.java - 演示了聚合(aggregation)功能. 關於聚合功能可參考DTrace.
  • JInfo.java - 演示了內置方法printVmArguments(), printProperties() 和printEnv() 的用法
  • JMap.java - 演示了內置方法dumpHeap()的用法. 即將目標應用的堆信息以二進制的形式dump出來
  • JStack.java - 演示了內置方法jstackAll()的用法, 即打印所有線程的堆棧信息.
  • LogTracer.java - 演示瞭如何深入實例方法(Logger.log)並調用內置方法(field() )打印私有屬性內容.
  • MemAlerter.java - 演示了使用@OnLowMememory 註解監控內存使用情況. 即堆內存中的年老代達到指定值時打印出內存信息.
  • Memory.java - 演示每隔4s打印一次內存統計信息.
  • MultiClass.java - 演示了通過使用正則表達式對多個類的多個方法進行trace.
  • NewComponent.java - 使用計數器每隔一段時間檢查當前應用中創建java.awt.Component的個數.
  • OnThrow.java - 當拋出異常時, 打印出異常堆棧信息.
  • ProbeExit.java - 演示@OnExit註解和內置exit(int)方法的用法
  • Profiling.java - 演示了對profile的支持.  // 我執行沒成功, BTrace內部有異常
  • Sizeof.java - 演示了內置的sizeof方法的使用.
  • SocketTracker.java - 演示了對socket的creation/bind方法的trace.
  • SocketTracker1.java - 同上, 只不過使用了@OnProbe.
  • SysProp.java - 演示了使用內置方法獲取系統屬性, 這裏是對 java.lang.System的getProperty方法進行trace.
  • SubtypeTracer.java - 演示瞭如何對指定超類的所有子類的指定方法進行trace.
  • ThreadCounter.java - 演示了在腳本中如何使用jvmstat 計數器. (jstat -J-Djstat.showUnsupported=true -name btrace.com.sun.btrace.samples.ThreadCounter.count 需要這樣來從外部通過jstat來訪問)
  • ThreadCounterBean.java - 同上, 只不過使用了JMX.
  • ThreadBean.java - 演示了對預編譯器的使用(並結合了JMX).
  • ThreadStart.java - 演示了腳本中DTrace的用法.
  • Timers.java - 演示了在一個腳本中同時使用多個@OnTimer
  • URLTracker.java - 演示了在每次URL.openConnection成功返回時打印出url. 這裏也使用了D語言腳本.
  • WebServiceTracker.java - 演示瞭如何根據註解進行trace.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章