天天看點

java性能調優及問題追蹤--Btrace的使用

在生産環境中經常遇到格式各樣的問題,如OOM或者莫名其妙的程序死掉。一般情況下是通過修改程式,添加列印日志;然後重新釋出程式來完成。然而,這不僅麻煩,而且帶來很多不可控的因素。有沒有一種方式,在不修改原有運作程式的情況下擷取運作時的資料資訊呢?如方法參數、傳回值、全局變量、堆棧資訊等。Btrace就是這樣一個工具,它可以在不修改原有代碼的情況下動态地追蹤java運作程式,通過hotswap技術,動态将跟蹤位元組碼注入到運作類中,對運作代碼侵入較小,對性能上的影響可以忽略不計。

基礎說明

由于Btrace會把腳本邏輯直接侵入到運作的代碼中,是以在使用上做很多限制:

不能建立對象

不能使用數組

不能抛出或捕獲異常

不能使用循環

不能使用synchronized關鍵字

屬性和方法必須使用static修飾

需要特别注意的是:不恰當的使用BTrace可能導緻JVM崩潰,如在BTrace腳本使用錯誤的class檔案,是以在上生産環境之前,務必在本地充分的驗證腳本的正确性。

Btrace可以做什麼?

接口性能變慢,分析每個方法的耗時情況;

當在Map中插入大量資料,分析其擴容情況;

分析哪個方法調用了System.gc(),調用棧如何;

執行某個方法抛出異常時,分析運作時參數;

....

參數說明:

指定分析方法的入口:@OnMethod

Btrace使用@OnMethod注解定義需要分析的方法入口

在@OnMethod注解中,需要指定class、method以及location等,class表明需要監控的類,method表明需要監控的方法,指定方式如下:

使用全限定名: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:在進入方法時,調用Btrace腳本

Kind.RETURN:方法執行完時,調用Btrace腳本,隻有把攔截位置定義為Kind.RETURN,才能擷取方法的傳回結果@Return和執行時間@Duration

Kind.CALL:分析方法中調用其它方法的執行情況,比如在execute方法中,想擷取add方法的執行耗時,必須把where設定成Where.AFTER

Kind.LINE:通過設定line,可以監控代碼是否執行到指定的位置

Kind.ERROR, Kind.THROW, Kind.CATCH

總結

Btrace能做的事情太多,但使用之前切記檢查腳本的可行性,一旦Btrace腳本侵入到系統中,隻有通過重新開機才能恢複。

通過jvisualvm插件的方式進行測試:

安裝Btrace插件

工具-->插件-->可用插件中找到BTrace Workbench進行安裝即可。

測試用例

package com.vmtools;

public class Counter {

    // 總數

    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);

}

import java.util.Random;

public class BtraceTest {

    public static void main(String[] args) throws Exception {

        Random random = new Random();

        // 計數器

        Counter counter = new Counter();

        while (true) {

            // 每次增加随機值

            counter.add(random.nextInt(10));

            Thread.sleep(1000);

        }

Btrace測試

運作上訴測試用例

jvisualvm中找到對應的程序id-->Trace application...-->分别進行相應的測試

擷取add()方法參數值和傳回值。

/* BTrace Script Template */

import com.sun.btrace.annotations.*;

import static com.sun.btrace.BTraceUtils.*;

//擷取add()方法參數值和傳回值。

@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

//定時擷取Counter類的屬性值totalCount。

    private static Object totalCount=0;

    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方法執行時間

//擷取add方法執行時間

    @TLS private static long startTime = 0;

        method="add"

        startTime = timeNanos();

    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.cnblogs.com/rwxwsblog/p/6248210.html,如需轉載請自行聯系原作者