package cn.freemethod.business; public interface SumInter { long sum(int num); }
package cn.freemethod.business; import javax.annotation.Resource; @Resource public class GSumInterImpl implements SumInter{ @Override public long sum(int num) { if(num % 2 == 0) return (1 + num) * (num / 2); else return (1 + num) * (num - 1)/2 + (num + 1) /2; } }
package cn.freemethod.business; import javax.annotation.Resource; public class SumInterImpl implements SumInter{ @Override public long sum(int num) { int sum = 0; for(int i =0 ;i<num;i++){ sum += i; } return sum; } @Resource public int doSomething(String arg1,Integer arg2){ return arg1.hashCode() + arg2; } }
package cn.freemethod.business; import java.util.Scanner; public class SumStart { public static void main(String[] args) { GSumInterImpl gSumInter = new GSumInterImpl(); SumInterImpl sumInter = new SumInterImpl(); final Scanner scanner = new Scanner(System.in); scanner.nextLine(); gSumInter.sum(10000); sumInter.sum(10000); sumInter.doSomething("hello",10); scanner.nextLine(); } }
這裏使用scanner.nextLine();是爲了等腳本啓動好了手動控制執行。java
package cn.freemethod.btracet; import com.sun.btrace.AnyType; import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.Sys.Env.printEnv; import static com.sun.btrace.BTraceUtils.Sys.Env.printProperties; import static com.sun.btrace.BTraceUtils.Sys.Memory.heapUsage; import static com.sun.btrace.BTraceUtils.Sys.Memory.nonHeapUsage; import static com.sun.btrace.BTraceUtils.Sys.VM.printVmArguments; import static com.sun.btrace.BTraceUtils.println; @BTrace public class OnMethodTrace { static{ println("--printVmArguments()--"); printVmArguments(); println("--printProperties()--"); printProperties(); println("--printEnv()--"); printEnv(); println("--heapUsage()--"); println(heapUsage()); println("--nonHeapUsage()--"); println(nonHeapUsage()); // exit(); } // @OnMethod(clazz="/java\\.util\\..*/",method="/.*/") @OnMethod(clazz="+java.util.Map",method="/.*/") public static void utilMethod(@ProbeClassName String probeClass, @ProbeMethodName String probeMethod) { println("utilMethod:" + probeClass + "." + probeMethod); } @OnMethod(clazz = "+cn.freemethod.business.SumInter", method = "sum", location = @Location(Kind.RETURN)) public static void onSum(@ProbeClassName String probeClass, @ProbeMethodName String probeMethod,@Return long sum, @Duration long duration){ println("onSum:"+ probeClass + "." + probeMethod + "_" + sum + "_" + duration); } @OnMethod(clazz = "cn.freemethod.business.SumInterImpl", method = "@javax.annotation.Resource", location = @Location(value = Kind.RETURN)) public static void onAnnotationResourceMethod(@Self Object self, String arg1, Integer arg2, @Return AnyType result){ println("onAnnotationResourceMethod:" + arg1 + "_" + arg2 + "_" + result); } @OnMethod(clazz = "@javax.annotation.Resource", location = @Location(value = Kind.LINE, line = 10)) public static void onLine(int line) { println("onLine reached line:10 " + line); } }
執行方式是在BTrace下載下載BTrace,解壓在bin目錄下執行:git
btrace pid OnMethodTrace.java
腳本要拷貝到BTrace的bin目錄下,不然就使用絕對路徑。pid能夠經過jps命令獲取到。github
更詳細的內容能夠參考BTrace使用正則表達式
咱們能夠看到OnMethodTrace腳本中的static塊部分,這一部分主要是打印jvm相關信息的,其實在實際中可能不多用,由於這些均可以jstat,jmap等工具獲取到。jvm
全部咱們仍是來看一下其餘的:ide
// @OnMethod(clazz="/java\\.util\\..*/",method="/.*/") @OnMethod(clazz="+java.util.Map",method="/.*/")
@OnMethod註解是用來攔截指定方法的,clazz屬性是指定類,能夠使用全限定名或者正則表達式,也能夠使用接口(前面添加"+")。method能夠是名字也能夠是正則表達式。匹配的時候儘可能讓攔截的方法範圍小一些,避免出現性能問題。工具
@ProbeClassName是注入被攔截方法所在的類的名字 @ProbeMethodName是注入被攔截方法的名字 @Return 是注入攔截時間 @Duration 是注入方法執行時間(單位是納秒,要除以1000000纔是毫秒,location必須是Kind.RETURN) @Self是注入調用被攔截方法的實例(this)性能
還能夠注入被攔截方法的參數,咱們看下面這個:測試
public static void onAnnotationResourceMethod(@Self Object self, String arg1, Integer arg2, @Return AnyType result)
注意:定義必定要按順序,必須是@Self,參數1,參數2...,@Returnthis
參數也能夠使用AnyType[] args來定義,返回值也能夠使用AnyType。
@OnMethod(clazz = "@javax.annotation.Resource", location = @Location(value = Kind.LINE, line = 10))
line是指定執行到指定行的時候執行,line=-1的時候是每行都會執行,加參數int line 注入當前行數
輸出的內容比較多,大概就像是下面的樣子: