java性能调优及问题追踪--Btrace的使用
在生產(chǎn)環(huán)境中經(jīng)常遇到格式各樣的問題,如OOM或者莫名其妙的進程死掉。一般情況下是通過修改程序,添加打印日志;然后重新發(fā)布程序來完成。然而,這不僅麻煩,而且?guī)砗芏嗖豢煽氐囊蛩?。有沒有一種方式,在不修改原有運行程序的情況下獲取運行時的數(shù)據(jù)信息呢?如方法參數(shù)、返回值、全局變量、堆棧信息等。Btrace就是這樣一個工具,它可以在不修改原有代碼的情況下動態(tài)地追蹤java運行程序,通過hotswap技術,動態(tài)將跟蹤字節(jié)碼注入到運行類中,對運行代碼侵入較小,對性能上的影響可以忽略不計。
基礎說明
由于Btrace會把腳本邏輯直接侵入到運行的代碼中,所以在使用上做很多限制:
- 不能創(chuàng)建對象
- 不能使用數(shù)組
- 不能拋出或捕獲異常
- 不能使用循環(huán)
- 不能使用synchronized關鍵字
- 屬性和方法必須使用static修飾
需要特別注意的是:不恰當?shù)氖褂肂Trace可能導致JVM崩潰,如在BTrace腳本使用錯誤的class文件,所以在上生產(chǎn)環(huán)境之前,務必在本地充分的驗證腳本的正確性。
Btrace可以做什么?
- 接口性能變慢,分析每個方法的耗時情況;
- 當在Map中插入大量數(shù)據(jù),分析其擴容情況;
- 分析哪個方法調(diào)用了System.gc(),調(diào)用棧如何;
- 執(zhí)行某個方法拋出異常時,分析運行時參數(shù);
- ....
參數(shù)說明:
指定分析方法的入口:@OnMethod
Btrace使用@OnMethod注解定義需要分析的方法入口
在@OnMethod注解中,需要指定class、method以及l(fā)ocation等,class表明需要監(jiān)控的類,method表明需要監(jiān)控的方法,指定方式如下:
- 使用全限定名:clazz="com.metty.rpc.common.BtraceCase", method="add"
- 使用正則表達式:clazz="/javax.swing../", method="/./"
- 使用接口:clazz="+com.ctrip.demo.Filter", method="doFilter"
- 使用注解:clazz="@javax.jws.WebService", method=""@javax.jws.WebMethod"
- 如果需要分析構造方法,需要指定method=""
指定方法攔截的位置:@Location
定義Btrace對方法的攔截位置,通過@Location注解指定,默認為Kind.ENTRY
- Kind.ENTRY:在進入方法時,調(diào)用Btrace腳本
- Kind.RETURN:方法執(zhí)行完時,調(diào)用Btrace腳本,只有把攔截位置定義為Kind.RETURN,才能獲取方法的返回結果@Return和執(zhí)行時間@Duration
- Kind.CALL:分析方法中調(diào)用其它方法的執(zhí)行情況,比如在execute方法中,想獲取add方法的執(zhí)行耗時,必須把where設置成Where.AFTER
- Kind.LINE:通過設置line,可以監(jiān)控代碼是否執(zhí)行到指定的位置
- Kind.ERROR, Kind.THROW, Kind.CATCH
總結
Btrace能做的事情太多,但使用之前切記檢查腳本的可行性,一旦Btrace腳本侵入到系統(tǒng)中,只有通過重啟才能恢復。
通過jvisualvm插件的方式進行測試:
安裝Btrace插件
工具-->插件-->可用插件中找到BTrace Workbench進行安裝即可。
測試用例
package com.vmtools;public class Counter {// 總數(shù)private static int totalCount = 0;public int add(int num) throws Exception {totalCount += num;sleep();return totalCount;}private void sleep() throws InterruptedException {Thread.sleep(1000);} } package com.vmtools;import java.util.Random; public class BtraceTest {public static void main(String[] args) throws Exception {Random random = new Random();// 計數(shù)器Counter counter = new Counter();while (true) {// 每次增加隨機值counter.add(random.nextInt(10));Thread.sleep(1000);}} }Btrace測試
運行上訴測試用例
jvisualvm中找到對應的進程id-->Trace application...-->分別進行相應的測試
獲取add()方法參數(shù)值和返回值。
/* BTrace Script Template */ import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.*;//獲取add()方法參數(shù)值和返回值。 @BTrace public class TracingScript {/* put your code here */@OnMethod(clazz="com.vmtools.Counter",method="add",location=@Location(Kind.RETURN))public static void func(int a,@Return int result) {println("trace: =======================");jstack();println(strcat("a:", str(a)));println(strcat("result:", str(result)));} }定時獲取Counter類的屬性值totalCount
/* BTrace Script Template */ import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.*;//定時獲取Counter類的屬性值totalCount。 @BTrace public class TracingScript {private static Object totalCount=0;/* put your code here */@OnMethod(clazz="com.vmtools.Counter",method="add",location=@Location(Kind.RETURN))public static void func(@Self com.vmtools.Counter counter) {totalCount = get(field("com.vmtools.Counter", "totalCount"), counter);}@OnTimer(2000)public static void print(){println(" ====== ");println(strcat("totalCount: ",str(totalCount)));} }獲取add方法執(zhí)行時間
/* BTrace Script Template */ import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.*;//獲取add方法執(zhí)行時間 @BTrace public class TracingScript {@TLS private static long startTime = 0;/* put your code here */@OnMethod(clazz="com.vmtools.Counter",method="add")public static void func(@Self com.vmtools.Counter counter) {startTime = timeNanos();}@OnMethod(clazz="com.vmtools.Counter",method="add",location=@Location(Kind.RETURN))public static void endExecute(@Duration long duration){ long time = timeNanos() - startTime; println(strcat("execute time(nanos): ", str(time))); println(strcat("duration(nanos): ", str(duration))); } }參考文檔:
- http://www.jianshu.com/p/dbb3a8b5c92f
- http://www.cnblogs.com/langtianya/p/4444025.html
總結
以上是生活随笔為你收集整理的java性能调优及问题追踪--Btrace的使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何在生产环境使用Btrace进行调试
- 下一篇: BTrace使用小结