調試工具BTrace 的使用--例子


BTrace 是一款利用hotSpot虛擬機可以動態替換class的特點而完成的,可以對online的程序動態的改變類的行為(一般為加些打印日志),進而進行線上調試的一個工具。

一篇淘寶技術團隊的博客:http://rdc.taobao.com/team/jm/archives/509

主要步驟如下(本次測試只針對BTrace和測試的程序在同一台機器上,remote的還待實驗):

1、下載地址:http://kenai.com/projects/btrace/downloads/download/releases/release-1.2.2/btrace-bin.zip

2、解壓到linux相應的目錄下。

3、編寫普通運行的程序如下:

package com.ddc.mem;

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);
           if(sleepTime%2==0)
               return true;
           else 
               return false;
       }
     
    }

Main函數運行:

package com.ddc.mem;

import java.util.Random;

public class CaseObjectMain {

       public static void main(String[] args) throws Exception{
              Random random=new Random();
              CaseObject object=new CaseObject();
              while(true){
                  boolean result=object.execute(random.nextInt(1000));
                 Thread.sleep(1000);
              }
           }
}

4、將以上兩個類編譯並運行 。

5、編寫BTrace 文件,按照java規范,java文件名稱為TracingScript.java

/* BTrace Script Template */
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;

@BTrace
public class TracingScript {
    /* put your code here */
/*指明要查看的方法,類*/
  @OnMethod(
     clazz="com.ddc.mem.CaseObject",
     method="execute",
     location=@Location(Kind.RETURN)
  )
/*主要兩個參數是對象自己的引用 和 返回值,其它參數都是方法調用時傳入的參數*/
   public static void traceExecute(@Self com.ddc.mem.CaseObject object,int sleepTime, @Return boolean result){
      println("調用堆棧!!");
       println(strcat("返回結果是:",str(result)));
      jstack();
      println(strcat("時間是:",str(sleepTime)));
   }

}

6、對於btrace文件夾加運行時路徑(java_home 和 classpath)

修改{btrace_home}/bin/btrace 文件

#! /bin/sh

#需要設置jdk的路徑,因為需要動態編譯,所以需要設置這個路徑
JAVA_HOME=/usr/lib/jvm/java-6-sun-1.6.0.22
#因為需要動態編譯,所以需要設置原類庫的classpath,主要是要編譯BTRACE文件,它里面肯定有依賴原類
CLASS_PATH=/data/testxiao/
#BTRACE_HOME路徑,編譯以及運行時都需要BTRACE自己的jar包
BTRACE_HOME=/data/btrace
if [ -z "$BTRACE_HOME" -o ! -d "$BTRACE_HOME" ] ; then
  # resolve links - $0 could be a link to btrace's home
  PRG="$0"
  progname=`basename "$0"`
  BTRACE_HOME=`dirname "$PRG"`/..
  BTRACE_HOME=`cd "$BTRACE_HOME" && pwd`
fi

if [ -f "${BTRACE_HOME}/build/btrace-client.jar" ] ; then
    if [ "${JAVA_HOME}" != "" ]; then
       case "`uname`" in
          Darwin*)
              # In Mac OS X, tools.jar is classes.jar and is kept in a 
              # different location. Check if we can locate classes.jar
              # based on ${JAVA_VERSION}
              TOOLS_JAR="/System/Library/Frameworks/JavaVM.framework/Versions/${JAVA_VERSION}/Classes/classes.jar"

              # if we can't find, try relative path from ${JAVA_HOME}. Usually,
              # /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home
              # is JAVA_HOME. (or whatever version beyond 1.6.0!)
              if [ ! -f ${TOOLS_JAR} ] ; then
                  TOOLS_JAR="${JAVA_HOME}/../Classes/classes.jar" 
              fi

              # If we still can't find, tell the user to set JAVA_VERSION.
              # This way, we can avoid zip file errors from the agent side
              # and "connection refused" message from client.
              if [ ! -f ${TOOLS_JAR} ] ; then
                  echo "Please set JAVA_VERSION to the target java version"
                  exit 1
              fi
          ;;
          *)
              TOOLS_JAR="${JAVA_HOME}/lib/tools.jar"
          ;;
       esac
       ${JAVA_HOME}/bin/java -Dcom.sun.btrace.probeDescPath=. -Dcom.sun.btrace.dumpClasses=false -Dcom.sun.btrace.debug=false -Dcom.sun.btrace.unsafe=false -cp ${BTRACE_HOME}/build/btrace-client.jar:${TOOLS_JAR}:/usr/share/lib/java/dtrace.jar:${CLASS_PATH} com.sun.btrace.client.Main $*
    else
       echo "Please set JAVA_HOME before running this script"
       exit 1
    fi
else
    echo "Please set BTRACE_HOME before running this script"
    exit 1
fi

 

7、jps   CaseObjectMain進程的pid,假設pid為1478 ,剛才的btrace  為TracingScript.java

    則運行命令為 :bin/btrace   1478 TracingScript.java

8、一切ok  

輸出如下:

調用堆棧!!
返回結果是:false
com.ddc.mem.CaseObject.execute(CaseObject.java:14)
com.ddc.mem.CaseObjectMain.main(CaseObjectMain.java:11)
時間是:483
調用堆棧!!
返回結果是:true
com.ddc.mem.CaseObject.execute(CaseObject.java:12)
com.ddc.mem.CaseObjectMain.main(CaseObjectMain.java:11)
時間是:998
調用堆棧!!
返回結果是:false
com.ddc.mem.CaseObject.execute(CaseObject.java:14)
com.ddc.mem.CaseObjectMain.main(CaseObjectMain.java:11)
時間是:611
調用堆棧!!
返回結果是:true
com.ddc.mem.CaseObject.execute(CaseObject.java:12)
com.ddc.mem.CaseObjectMain.main(CaseObjectMain.java:11)
時間是:524

 

表明其實已經改變了原有的輸出並加上了打印日志 。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM