BTrace:Byte trace,通過動態字節碼將跟蹤操作代碼插入到正在運行的Java程序的類中。
簡單來說,就是通過 instrument + asm,對正在運行中的類,進行動態增強。使用過Jrebel 的對此可能非常熟悉,原理類似。
使用場景
基於此,btrace 被用於線上排查問題,追蹤bug。最常用的就是跟VisualVM 一起用來排查問題。
概念
探測點
限制
爲保證對線上代碼沒有過多侵入,同時也沒有副作用(比如引起了異常、修改變量、中斷代碼邏輯等),對btrace做了一下限制:
不能創建對象
不能創建數組
不能拋出和捕獲異常
不能調用任何對象方法和靜態方法
不能給目標程序中的類靜態屬性和對象的屬性進行賦值
不能有外部、內部和嵌套類
不能有同步塊和同步方法
不能有循環(for, while, do..while)
不能繼承任何的類
不能實現接口
不能包含assert斷言語句
使用
它的使用很簡單,有兩個方式;與visualVM一起使用;命令行操作腳本。
與VisualVM配合使用
VisualVM一般用來查看java服務運行時內存的。
待整理
操作腳本
有三步:
1.寫腳本
這個可以新建個項目,引入這些包
dependencies {
compile group: 'com.sun.tools.btrace', name: 'btrace-agent', version: '1.2.3'
compile group: 'com.sun.tools.btrace', name: 'btrace-client', version: '1.2.3'
compile group: 'com.sun.tools.btrace', name: 'btrace-boot', version: '1.2.3'
}
代碼也簡單:
@BTrace(unsafe = true)
public class PrinterTest {
@OnMethod(
clazz = "com.hust.service.MyService", method = "print", location = @Location(Kind.ENTRY)
)
public static void called(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args) {
BTraceUtils.printArray(args);
BTraceUtils.println("className: " + pcn);
BTraceUtils.println("MethodName: " + pmn);
BTraceUtils.println();
}
}
指定方法和探測點。
2.本地安裝
在官網下載,解壓到本地,然後加環境變量 BTRACE_HOME 即可
BTRACE_HOME=/data/btrace
另外,btrace運行需要有JAVA_HOME ,沒有的話可以簡單配置下
安裝java後查看java_home:
/usr/libexec/java_home -V
我的電腦上是
/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home
然後加JAVA_HOME 到環境變量
cd ~
vim .bash_profile
在家目錄下,編輯 該文件,如果沒有則創建:
JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_191.jdk/Contents/Home
CLASSPAHT=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
PATH=$JAVA_HOME/bin:$PATH:
export JAVA_HOME
export CLASSPATH
export PATH
編輯後保存退出。
爲了使修改立刻生效,執行:
source .bash_profile
3.跟蹤
先找到java服務器的pid,比如:
ps -ef | grep name
找到後就可以執行以下命令去追蹤了:
btrace pid trace_script
其中pid是你要追蹤的java服務進程,trace_script 是第一步寫代碼編譯後的腳本,即 .class 文件
注意事項
BTrace 腳本可以被用來修改線上的代碼,要注意的是被修改的字節碼不會被還原。因爲增強類被類類加載器加載到方法區了,但是沒有卸載類的方式,增強類會一直留在虛擬機裏,直到JVM重啓。