教程英文版來源:https://github.com/btraceio/btrace/blob/master/docs/usersguide.html
BTrace用戶指南
BTrace是一種安全,動態的Java跟蹤工具。BTrace通過動態(字節碼)檢測正在運行的Java程序的類來工作。BTrace將跟蹤操作插入到正在運行的Java程序的類中,並對跟蹤的程序類進行熱交換。
BTrace術語
- 探針點
- 執行一組跟蹤語句的“location”或“event”。探針點是我們想要執行一些跟蹤語句的感興趣的“位置”或“事件”。
- 跟蹤操作或操作
- 探測器“觸發”時執行的跟蹤語句。
- 行動方法
- 探測器觸發時執行的BTrace跟蹤語句是在類的靜態方法中定義的。這種方法稱為“動作”方法。
BTrace程序結構
BTrace程序是一個普通的Java類,它有一個或多個public static void
用BTrace注釋注釋的方法。注釋用於指定跟蹤的程序“位置”(也稱為“探測點”)。跟蹤操作在靜態方法體內指定。這些靜態方法稱為“動作”方法。
BTrace限制
為了保證跟蹤操作是“只讀”(即跟蹤操作不會改變跟蹤的程序狀態)和有界(即跟蹤操作在有限時間內終止),BTrace程序只允許執行一組有限的行動。特別是BTrace類
- 不能創建新的對象。
- 不能創造新的陣列。
- 不能拋出異常。
- 不能捕捉異常。
- 不能讓任意實例或靜態方法調用-只有
public static
方法的com.sun.btrace.BTraceUtils
類可以從BTrace程序調用。 - 不能分配到目標程序的類和對象的靜態或實例字段。但是,BTrace類可以分配給它自己的靜態字段(“跟蹤狀態”可以變異)。
- 不能有實例字段和方法。
static public void
BTrace類只允許返回方法。所有領域都必須是靜態的。 - 不可以具有外,內,嵌套的或局部類。
- 不可以具有同步塊或同步方法。
- 不能有環(
for, while, do..while
) - 不可以延伸任意類(超類必須java.lang.Object中)
- 不可以實現接口。
- 不可以包含斷言語句。
- 不可以使用類文字。
一個簡單的BTrace程序
// import all BTrace annotations
import com.sun.btrace.annotations.*;
// import statics from BTraceUtils class
import static com.sun.btrace.BTraceUtils.*;
// @BTrace annotation tells that this is a BTrace program
@BTrace
public class HelloWorld {
// @OnMethod annotation tells where to probe.
// In this example, we are interested in entry
// into the Thread.start() method.
@OnMethod(
clazz="java.lang.Thread",
method="start"
)
public static void func() {
// println is defined in BTraceUtils
// you can only call the static methods of BTraceUtils
println("about to start a thread!");
}
}
上面的BTrace程序可以針對正在運行的Java進程運行。這個程序將打印“即將開始一個線程!” 每當目標程序即將通過Thread.start()
方法啟動一個線程時,在BTrace客戶端。還有其他有趣的探索點可能。例如,我們可以在從方法返回時插入跟蹤操作,從方法返回異常,在方法中獲取或設置字段,創建對象/數組,行號,拋出異常。有關詳細信息,請參閱 @OnMethod和其他注釋。
運行BTrace的步驟
- 查找要跟蹤的目標Java進程的進程ID。您可以使用jps工具查找pid。
- 編寫BTrace程序 - 您可能想要開始修改其中一個 示例。
- 通過以下命令行運行btrace工具:
btrace <pid> <btrace-script>
BTrace命令行
BTrace使用命令行工具btrace運行,如下所示:
btrace [-I <include-path>] [-p <port>] [-cp <classpath>] <pid> <btrace-script> [<args>]
哪里
include-path
是一組搜索頭文件的包含目錄。BTrace包含一個簡單的預處理,支持#define,#include和條件編譯。它是不是像一個完整的C / C ++預處理程序-但有用的子集。請參閱示例“ThreadBean.java”。如果未指定-I,則BTrace將跳過預處理器調用步驟。port
是BTrace代理偵聽的端口。這是可選參數。classpath
是一組目錄,jar文件,其中BTrace在編譯期間搜索類。默認為“。”。pid
是跟蹤的Java程序的進程IDbtrace-script
是跟蹤計划。如果它是“.java”,則在提交之前編譯它。或者,假設它是預編譯的[即,它必須是.class]並提交。
可選的
port
是BTrace代理程序偵聽客戶端的服務器套接字端口。默認是2020。path
是用於編譯BTrace程序的類路徑。默認為“。”。args
是傳遞給BTrace程序的命令行參數。BTrace程序可以使用內置函數“$”和“$ length”訪問它們。
預編譯BTrace腳本
可以使用btracec腳本預編譯BTrace程序。btracec是一個類似javac的程序,它接受一個BTrace程序並生成一個.class文件。
btracec [-I <include-path>] [-cp <classpath>] [-d <directory>] <one-or-more-BTrace-.java-files>
哪里
include-path
是一組搜索頭文件的包含目錄。BTrace包含一個簡單的預處理,支持#define,#include和條件編譯。它是不是像一個完整的C / C ++預處理程序-但有用的子集。請參閱示例“ThreadBean.java”。如果未指定-I,則BTrace將跳過預處理器調用步驟。classpath
是用於編譯BTrace程序的類路徑。默認為“。”directory
是存儲編譯的.class文件的輸出目錄。默認為“。”。
此腳本使用BTrace編譯器類 - 而不是常規javac,因此將在編譯時驗證您的BTrace程序[以便您可以在運行時避免BTrace驗證錯誤]。
使用BTrace代理啟動應用程序
到目前為止,我們已經了解了如何跟蹤正在運行的Java程序。也可以在其中啟動使用BTrace代理的應用程序。如果您想從“開始”開始跟蹤應用程序,您可能希望使用BTrace代理啟動應用程序並指定跟蹤腳本[即,BTrace代理是按需加載以及預先加載可加載代理程序]您可以使用以下命令啟動應用程序並指定BTrace腳本文件。但是,您需要預編譯BTrace腳本以實現此類用法。
java -javaagent:btrace-agent.jar=script=<pre-compiled-btrace-script> <MainClass> <AppArguments>
以這種方式啟動應用程序時,跟蹤輸出將轉到當前目錄中名為<btrace-class-file-name> .btrace的文件。此外,您可以通過指定noServer=true
BTrace代理的參數來避免為其他遠程BTrace客戶端啟動服務器。
有一個方便的腳本叫做btracer來執行上述操作:
btracer <pre-compiled-btrace.class> <application-main-class> <application-args>
BTrace注釋
方法注釋
- @ com.sun.btrace.annotations.OnMethod 注釋可用於指定方法中的目標類,目標方法和“位置”。當匹配方法到達指定位置時,將調用由此批注注釋的操作方法。在OnMethod注釋中,跟蹤類名由“clazz”屬性指定,跟蹤方法由“method”屬性指定。“clazz中”可以是一個完全合格的類名(像
java.awt.Component
或兩個前進內指定正則表達式斜線。參考樣品 NewComponent.java和Classload.java。正則表達式可以匹配的零個或更多的類在這種情況下所有匹配類儀表化的。例如/java\\.awt\\..+/
匹配java.awt包中的所有類。此外,方法名稱也可以是正則表達式 - 匹配零個或多個方法。請參閱示例MultiClass.java。還有另一種方法可以抽象地指定跟蹤類和方法。可以通過注釋指定跟蹤的類和方法。例如,如果將“clazz”屬性指定為@javax.jws.WebService
BTrace,則將檢測由WebService批注注釋的所有類。類似地,方法級別注釋可用於抽象地指定方法。請參閱示例 WebServiceTracker.java。也可以將正則表達式與注釋結合起來 - 比如說@/com\\.acme\\..+/
匹配由任何與給定正則表達式匹配的注釋注釋的任何類。通過指定超類型可以匹配多個類。即,匹配給定超類型的子類型的所有類。+java.lang.Runnable
匹配實現java.lang.Runnable接口的所有類。請參閱示例SubtypeTracer.java。 - @ com.sun.btrace.annotations.OnTimer 注釋可用於指定必須每N毫秒定期運行一次的跟蹤操作。時間段被指定為此注釋的長“值”屬性。請參閱 Histogram.java示例
- @ com.sun.btrace.annotations.OnError 注釋可用於指定在跟蹤某些其他探測操作時拋出任何異常時運行的操作。當同一BTrace類中的任何其他BTrace操作方法拋出任何異常時,將調用由此批注注釋的BTrace方法。
- @ com.sun.btrace.annotations.OnExit 注釋可用於指定當BTrace代碼調用“exit(int)”內置函數以完成跟蹤“會話”時運行的操作。請參閱示例 ProbeExit.java。
- @ com.sun.btrace.annotations.OnEvent 注釋用於將跟蹤方法與BTrace客戶端發送的“外部”事件相關聯。當BTrace客戶端發送“事件”時,將調用由此注釋注釋的BTrace方法。客戶端可以根據某種形式的用戶請求發送事件(如按Ctrl-C或GUI菜單)。字符串值可以用作事件的名稱。這樣,只要外部事件“觸發”,就可以執行某些跟蹤動作。截至目前,只要使用按Ctrl-C(SIGINT),命令行BTrace客戶端就會發送“事件”。在SIGINT上,顯示控制台菜單以發送事件或退出客戶端[這是SIGINT的默認設置]。請參閱示例 HistoOnEvent.java
- @ com.sun.btrace.annotations.OnLowMemory 注釋可用於跟蹤內存閾值超出事件。請參閱示例 MemAlerter.java
- @ com.sun.btrace.annotations.OnProbe 注釋可用於指定以避免在BTrace腳本中使用實現內部類。@OnProbe探針規范由BTrace VM代理映射到一個或多個@OnMethod規范。目前,此映射是使用XML探測描述符文件[由BTrace代理訪問]完成的。請參閱示例 SocketTracker1.java 和關聯的探測描述符文件 java.net.socket.xml。運行此示例時,需要將此xml文件復制到目標JVM運行的目錄中(或修復btracer.bat中的probeDescPath選項以指向.xml文件所在的位置)。
參數注釋
- @ com.sun.btrace.annotations.Self 注釋可用於標記一個參數以保存* this *(或* self *)值。請參閱示例 AWTEventTracer.java或 AllCalls1.java
- @ com.sun.btrace.annotations.Return 注釋可用於標記保存返回值的參數。請參閱示例 Classload.java
- @ com.sun.btrace.annotations.CalledInstance 注釋可用於標記保存被調用實例值的參數。請參閱示例 AllCalls2.java
- @ com.sun.btrace.annotations.CalledMethod 可用於標記包含被調用方法名稱的參數。請參閱示例 AllCalls1.java或 AllCalls2.java
字段注釋
@com.sun.btrace.annotations.Export
注釋可以與BTrace字段(靜態字段)一起使用,以指定該字段必須映射到jvmstat計數器。使用此功能,BTrace程序可以將跟蹤計數器公開給外部jvmstat客戶端(例如jstat)。請參閱示例 ThreadCounter.java@com.sun.btrace.annotations.Property
注釋可用於將特定(靜態)字段標記為MBean特性。如果BTrace類具有至少一個具有@Property屬性的靜態字段,則創建MBean並向平台MBean服務器注冊。諸如VisualVM,jconsole之類的JMX客戶端可用於查看此類BTrace MBean。將BTrace附加到目標程序后,可以將VisualVM或jconsole附加到同一程序並查看新創建的BTrace MBean。使用VisualVM和jconsole,您可以使用MBeans選項卡查看BTrace域並查看其屬性。請參閱示例ThreadCounterBean和 HistogramBean.java。@com.sun.btrace.annotations.TLS
注釋可以與BTrace字段(靜態字段)一起使用,以指定該字段是線程本地字段。每個Java線程都獲得該字段的單獨“副本”。BTrace程序可以使用這些線程本地字段來識別我們是否從同一線程到達多個探測操作。請參閱示例 OnThrow.java和 WebServiceTracker.java
類注釋
@com.sun.btrace.annotations.DTrace
注釋可用於將簡單的單線程D-script(在BTrace Java類中內聯)與BTrace程序相關聯。請參閱示例DTraceInline.java。@com.sun.btrace.annotations.DTraceRef
注釋可用於將D-script(存儲在單獨的文件中)與BTrace程序相關聯。請參閱示例DTraceRefDemo.java。@com.sun.btrace.annotations.BTrace
必須使用注釋將給定的Java類指定為BTrace程序。此注釋由BTrace編譯器以及BTrace代理強制執行。
DTrace集成
Solaris DTrace是一個用於Solaris程序的動態,安全的跟蹤系統 - 內核和用戶登陸程序。由於brace與DTrace和BTrace有明顯的相似之處,因此可以預期整合b / w BTrace和DTrace。BTrace與DTrace集成的方式有兩種。
- BTrace程序可以通過調用來引發DTrace探測
dtraceProbe
- 請參閱上面提到的BTraceUtils javadoc。要使此功能起作用,您需要在Solaris 10或更高版本上運行。對於其他平台(Solaris 9或更低版本或任何其他操作系統),dtraceProbe()
將是無操作。 - BTrace程序可以將D-script與它相關聯 - 通過@DTrace注釋(如果D-script是一個簡單的單行),或者如果D-script較長並且因此存儲在BTrace程序之外,則通過@DTraceRef。請參閱下面的BTrace樣品部分中的DTrace集成樣品。此功能使用DTrace Java API。要使此DTrace功能起作用(oe,能夠運行相關的D-script),您需要在Solaris 11 build 35或更高版本上運行。您可能想要檢查您的計算機上是否有/usr/share/lib/java/dtrace.jar。@DTrace和@DTraceRef注釋在其他平台(Solaris 10或更低版本或任何其他OS)上被忽略。
BTrace樣品
關於樣品的一行:
- AWTEventTracer.java - 通過檢測EventQueue.dispatchEvent()方法演示AWT事件的跟蹤。可以通過instanceof檢查過濾事件。此示例僅過濾和打印焦點事件。
- AllLines.java - 演示基於行號的BTrace探測器。可以探測任何類(或類)和行號。當達到指定類的指定行號時,將觸發BTrace探測並執行相應的操作。
- ArgArray.java - 在java.io包中的每個類的每個readXXX方法中打印所有輸入參數。在探針規范中演示參數數組訪問和多個類/方法匹配。
- Classload.java -
defineClass
由任何用戶定義的類加載器在每個成功的類加載(返回)上打印堆棧跟蹤。 - CommandArg.java - 演示BTrace命令行參數訪問。
- Deadlock.java - 演示@OnTimer探針和
deadlock()
內置函數。 - DTraceInline.java - 演示@DTrace注釋,將簡單的單行D-script與BTrace程序相關聯。
- DTraceRefDemo.java - 演示@DTraceRef注釋以將D-script文件與BTrace程序相關聯。此示例將classload.d與其自身相關聯。
- FileTracker.java - 通過探測
File{Input/Output}Stream
構造函數入口點打印文件以進行讀/寫。 - FinalizeTracker.java - 演示我們可以打印對象的所有字段以及訪問(私有)字段(只讀)。這在調試/故障排除方案中很有用。此示例打印有關java.io.FileInputStream類的close()/ finalize()方法的信息。
- Histogram.java - 演示使用BTrace地圖收集直方圖(
javax.swing.JComponent
由app創建的對象 - 按子類名稱和計數的直方圖)。 - HistogramBean.java - 演示JMX集成。此示例使用
@Property
注釋公開Map作為MBean屬性。 - HistoOnEvent.java - 演示基於客戶端事件獲取跟蹤輸出。在BTrace客戶端啟動腳本后,按Ctrl-C獲取發送事件或退出的菜單。在發送事件時,將打印直方圖。這樣,客戶端可以在需要時“拉”跟蹤輸出,而不是BTrace代理總是或基於計時器推送跟蹤輸出。
- JdbcQueries.java - 演示BTrace聚合工具。此工具類似於 DTrace聚合工具。
- JInfo.java -演示
printVmArguments()
,printProperties()
並printEnv()
內置函數。 - JMap.java - 演示
dumpHeap()
內置函數以轉儲(hprof二進制格式)目標應用程序的堆轉儲。 - JStack.java - 演示
jstackAll()
內置函數以打印所有線程的堆棧跟蹤。 - LogTracer.java - 演示捕獲到實例方法(Logger.log)和打印私有字段值(LogRecord對象)
field()
和objectValue()
內置函數。 - MemAlerter.java - 演示@OnLowMememory注釋對低內存事件的跟蹤。
- Memory.java - 通過計時器探測器每4秒打印一次內存統計信息。演示內存統計內置函數。
- MultiClass.java - 演示使用正則表達式
clazz
和注釋method
字段將跟蹤代碼插入到多個類的多個方法中@OnMethod
。 - NewComponent.java - 跟蹤每個
java.awt.Component
創建並遞增計數器並根據計時器打印計數器。 - OnThrow.java - 每次創建任何異常實例時都會打印異常堆棧跟蹤。在大多數情況下,創建后會立即拋出異常。所以,我們得到了投擲點的堆棧跟蹤。
- ProbeExit.java - 演示
@OnExit
探針和exit(int)
內置函數。 - Sizeof.java - 演示“sizeof”內置函數,可用於獲取(近似)給定Java對象的大小。使用此內置功能可以獲得按尺寸方式的直方圖等。
- SocketTracker.java - 打印每個服務器socker創建/綁定和客戶端套接字接受。
- SocketTracker1.java - 類似於SocketTracker.java示例,但此示例使用@OnProbe探針以避免在BTrace程序中使用Sun特定的套接字通道實現類。而是BTO代理將@OnProbe探針映射到@OnMethod探針。
- SysProp.java - 演示可以探測System類(如java.lang.System)並在action方法中調用BTrace內置函數。
- SubtypeTracer.java - 演示可以匹配給定超類型的所有子類型。
- ThreadCounter.java - 演示如何使用BTrace程序中的jvmstat計數器。
- ThreadCounterBean.java - 演示將BTrace程序公開為具有一個屬性的JMX bean(使用@Property注釋)。
- ThreadBean.java - 演示了BTrace [和JMX integratio]的預處理器的使用。
- ThreadStart.java - 演示從BTrace程序中提升DTrace探測器。另請參見 jthread.d - 關聯的D-script。只要跟蹤的程序進入java.lang.Thread.start()方法,此示例就會引發DTrace USDT探測。BTrace程序將JavaThread的名稱傳遞給DTrace。
- Timers.java -
@OnTimer
在BTrace程序中演示多個計時器探測器()。 - URLTracker.java - 每次
URL.openConnection
成功返回時打印URL 。該程序也使用jurls.d D-script(顯示通過DTrace打開的URL的直方圖)。 - WebServiceTracker.java - 通過指定類和方法級別注釋而不是類和方法名稱來演示跟蹤類和方法。