有時候你需要分析或優化正在執行的 Java 程式。最直觀但侵入性最強的方式是大量插入 System.out.println 或日誌輸出,但這會讓程式碼變得混亂難維護。這正是面向切面程式設計(AOP)關注的重點——它能在不修改目標程式碼的前提下,於滿足特定條件時插入操作邏輯。將切面植入程式碼的過程稱為「織入」,主要有三種方式:原始碼織入(編譯前)、位元碼織入(編譯後)、動態織入(運行時)。BTrace 正是採用動態織入技術,無需重新編譯或停止應用,即可像外掛一樣「插入」運行中的 JVM 進行監控。
BTrace 是一個非侵入式的 Java 程式動態追蹤工具。它只讀取程式資訊,不修改任何程式碼。你可以編寫與 Java 語法完全相容的腳本,定義想要監控的內容(如方法呼叫、參數、回傳值、執行時間、堆疊追蹤等)。最大優勢在於:零停機、零重編譯、零程式碼修改。
jps 取得目標進程 PID。btrace -cp <btrace.jar路徑> <pid> <腳本.java>範例程式包含三個類別:
Data:快取資料物件,含 content 欄位。DataAccessor:核心邏輯,使用 WeakReference 實作快取。getData(key) 若快取命中則回傳,否則建立新物件放入快取。Client:模擬隨機金鑰存取。避免快取物件阻礙 GC 回收,防止記憶體洩漏。但需注意 WeakReference.get() 可能回傳 null,必須雙重檢查。
import static com.sun.btrace.BTraceUtils.*;
import com.sun.btrace.annotations.*;
@BTrace public class TraceCache {
@OnMethod(clazz="DataAccessor", method="getData")
public static void onGetData(@ProbeMethodName String m, String key) {
println("Enter " + m + " key=" + key);
}
@OnMethod(clazz="DataAccessor", method="getData", location=@Location(Kind.RETURN))
public static void onGetDataReturn(@Return Data result) {
println("Return: " + (result != null ? result.getContent() : "null"));
}
}
WeakReference 清除時機。BTrace 讓你在生產環境中以極低成本獲得程式運行細節,是排查效能瓶頸、死鎖、記憶體洩漏、異常拋出等疑難雜症的神兵利器。掌握 BTrace,等於擁有了「不停機 X 光機」。