多時候在online的應用出現問題時,不少時候咱們須要知道更多的程序的運行細節,但又不可能在開發的時候就把程序中全部的運行細節都打印到日誌上,一般這個時候能採起的就是修改代碼,從新部署,而後再觀察,但這種方法對於online應用來講不是很好,另一方面若是碰到很差改的代碼,例如引用的其餘的外部的包什麼的,就很麻煩了,BTrace就是一個能夠在不改代碼、不重啓應用的狀況下,動態的查看程序運行細節的工具,其官方網站在此:http://kenai.com/projects/btrace/,在這篇blog中,就來看看如何用BTrace來動態的監測方法的一些運行細節情況。
BTrace經過動態的掛接用java寫的代碼到運行時上來獲取到一些運行細節,例如典型的使用btrace的方法爲:
btrace-cp[btrace的jar所在的路徑,默認爲btrace/build下][pid][須要運行的java代碼]
例如一段這樣的代碼:java
[java] import java.util.Random; public class Case1{ public static void main(String[] args) throws Exception{ Random random=new Random(); CaseObject object=new CaseObject(); boolean result=true; while(result){ result=object.execute(random.nextInt(1000)); Thread.sleep(1000); } } } public class CaseObject{ private static int sleepTotalTime=0; public boolean execute(int sleepTime) throws Exception{ System.out.println("sleep: "+sleepTime); sleepTotalTime+=sleepTime; Thread.sleep(sleepTime); return true; } } [/java]
如在程序運行的狀況下,想知道調用CaseObject的execute方法的如下幾種狀況,在BTrace中能夠這麼作:
一、調用此方法時傳入的是什麼參數,返回的是什麼值,當時sleepTotalTime是多少?
BTrace腳本以下:dom
[java] import static com.sun.btrace.BTraceUtils.*; import com.sun.btrace.annotations.*; @BTrace public class TraceMethodArgsAndReturn{ @OnMethod( clazz="CaseObject", method="execute", location=@Location(Kind.RETURN) ) public static void traceExecute(@Self CaseObject instance,int sleepTime,@Return boolean result){ println("call CaseObject.execute"); println(strcat("sleepTime is:",str(sleepTime))); println(strcat("sleepTotalTime is:",str(get(field("CaseObject","sleepTotalTime"),instance)))); println(strcat("return value is:",str(result))); } } [/java]
而後直接執行btrace-cpbtrace/build[pid]TraceMethodArgsAndReturn.java就能夠了。
當程序中調用到caseobject的execute方法時,就會在btrace的console中輸出相應的信息。
二、execute方法執行耗時是多久?
BTrace腳本以下:ide
[java] import static com.sun.btrace.BTraceUtils.*; import com.sun.btrace.annotations.*; @BTrace public class TraceMethodExecuteTime{ @TLS static long beginTime; @OnMethod( clazz="CaseObject", method="execute" ) public static void traceExecuteBegin(){ beginTime=timeMillis(); } @OnMethod( clazz="CaseObject", method="execute", location=@Location(Kind.RETURN) ) public static void traceExecute(int sleepTime,@Return boolean result){ println(strcat(strcat("CaseObject.execute time is:",str(timeMillis()-beginTime)),"ms")); } } [/java]
三、誰調用了execute方法?
BTrace腳本以下:工具
[java] import static com.sun.btrace.BTraceUtils.*; import com.sun.btrace.annotations.*; @BTrace public class TraceMethodCallee{ @OnMethod( clazz="CaseObject", method="execute" ) public static void traceExecute(){ println("who call CaseObject.execute :"); jstack(); } } [/java]
四、有沒有人調用CaseObject中的哪一行代碼?
BTrace腳本以下:網站
[java] import static com.sun.btrace.BTraceUtils.*; import com.sun.btrace.annotations.*; @BTrace public class TraceMethodLine{ @OnMethod( clazz="CaseObject", location=@Location(value=Kind.LINE,line=5) ) public static void traceExecute(@ProbeClassName String pcn,@ProbeMethodName String pmn,int line){ println(strcat(strcat(strcat("call ",pcn),"."),pmn)); } } [/java]
從上面可看出,在有了BTrace後,要動態的跟蹤代碼的運行細節仍是很是爽的,更多的細節的操做請你們查看BTrace的UserGuide。ui