`
kavy
  • 浏览: 891157 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

调试工具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

 

表明其实已经改变了原有的输出并加上了打印日志 。

 

 

BTrace本身也是可以独立运行的程序,作用是在不停止目标程序运行的前提下,通过HotSpot虚拟机的HotSwap技术动态插入原本不存在的调试代码。

比如遇到了我们的程序出问题,而又没有足够的打印语句时,我们一般的方法是不得不停掉服务,然后修改代码,增加打印语句,重新编译重新运行来解决,效率很低。

但有了BTrace,我们需要做的就很简单了,举例说明:

比如环境上运行着一个简单程序:

package com.huawei.main;

import java.io.BufferedReader;

import java.io.InputStreamReader;

 

public class Main

{

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

    { 

        Main test = new Main();

        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        for (int i = 0; i < 10; i++)

        {

            reader.readLine();

            int a = (int) Math.round(Math.random() * 1000);

            int b = (int) Math.round(Math.random() * 1000);

            System.out.println(test.add(a, b));

        }

    }

    public int add(int a, int b)

    {

        return a + b;

    }

}

该程序从控制台中获取一个输入,然后生成两个随机数,相加后将结果打印出来

对于add方法没有日志打印,如果想在不改变程序的前提下知道程序运行时add函数的入参和返回值,我们可以:

1. 在环境上解压BTrace工具包

比如解压到:/opt/eucalyptus/test/目录下

2. 编写BTrace脚本,对于脚本还是需要时间学习和实践的。如下TraceScript.java(注意在Linux下,这个文件应该是ANSI格式,否则会报illegal character: \65279的异常):

import com.sun.btrace.annotations.*;

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

 

@BTrace

public class TraceScript

{

      @OnMethod(clazz="com.huawei.main.Main", method="add", location=@Location(Kind.RETURN))

      public static void func(int a, int b, @Return int result)

      {

              jstack();

              println(strcat("para A: ", str(a)));

              println(strcat("para B: ", str(b)));

              println(strcat("result: ", str(result)));

      }

}

将该脚本放在环境目录下,比如:/opt/eucalyptus/test/TraceScript.java

test目录结构如下:

除TraceScript.java外都是BTrace解压后的文件。

3. 利用jps得到Main程序的进程号(比如28772),到BTrace目录的bin目录下执行语句:

/opt/eucalyptus/test/bin # ./btrace 28772 ../TraceScript.java

4. 在Main程序的控制台下输入字符,回车,会看到BTrace的输出:

总结:BTrace用法还有很多,打印调用堆栈、参数、返回值只是最基本的应用,在BTrace网址上有使用BTrace进行性能监视、定位连接泄露、内存泄露、解决多线程竞争问题等例子。

注意:如果一个java程序是以普通用户权限运行,则不能在root权限下对其进行btrace,一定先要切换到普通用户。

 

 

BTrace源码的查探点一般是类级别的,指定类名后,这个设置将对此类的所有对象都生效。 

但有时我们只想监控这个类里的某个对象,比如某个业务类中的某个HashSet类型的成员变量。  

BTrace对此没有直接的支持,但有的情况下你可以考虑一种变通的方法: 

  1. 先写一个BTrace源码找到你要访问的特定对象的hashCode. 
       

Java代码  收藏代码
  1. int hashCode = BTraceUtils.identityHashCode(set)  



  2. 然后另写BTrace源码,按hashCode过滤对象: 

Java代码  收藏代码
  1. @OnMethod(clazz="java.util.HashSet", method="/.*/")  
  2. public static void allListMethodsEntry(@Self java.util.HashSet set) throws Exception {  
  3.               if(identityHashCode(set) ==  hashCode ) {          
  4.                      ...  
  5.               }  
  6. }  




不得不承认,这种办法的适用场景非常有限: 
   你的目标应该是一个长寿对象(比如系统中的单例),这个对象的hashCode一直不变。 

分享到:
评论

相关推荐

    性能工具之Java调试工具BTrace入门(csdn)————程序.pdf

    【Java调试工具BTrace入门】 在Java开发过程中,遇到应用程序性能问题或需要进行问题定位时,通常会依赖日志分析、远程调试等方法。然而,这些方法可能存在局限性,如日志信息不足、远程调试影响服务运行、频繁修改...

    btrace调试工具

    **BTrace调试工具详解** BTrace是一款强大的Java应用程序动态跟踪工具,它允许开发者在不修改源代码或重新启动应用的情况下,对正在运行的Java应用程序进行实时的性能分析和诊断。这款工具的核心在于其字节码注入...

    java btrace线上代码调试工具

    java btrace线上代码调试工具,可以用来在不关闭线上系统的情况下动态植入调试代码

    btrace1.3.9

    【标题】"btrace1.3.9"指的是BTrace工具的一个特定版本,1.3.9,这是一款强大的Java应用程序动态跟踪工具。BTrace利用Java的JVMTI(Java Virtual Machine Tool Interface)和Serviceability Agent(SA)来提供安全、...

    Btrace非侵入式调试Java程序神奇linux版

    标题中的“Btrace非侵入式调试Java程序神奇linux版”指出,这是一个专为Linux系统设计的工具,名为Btrace,它主要用于非侵入式的Java程序调试。非侵入式意味着Btrace可以在不修改或重新编译原始Java代码的情况下,对...

    jdk1.8-Btrace.rar

    【标题】"jdk1.8-Btrace.rar"指的是一个针对Java开发的特殊工具包,它包含了一个名为Btrace的在线检测插件。这个插件专为Java开发者设计,旨在帮助他们在应用程序运行时进行问题的实时定位,而无需停止或重启服务。...

    BTrace-一个用于Java平台的安全动态的跟踪工具

    总的来说,BTrace是一个强大的Java性能分析工具,它提供了动态字节码注入的手段,使得开发者能够实时监测和调试运行中的Java应用程序,从而更有效地进行性能优化和问题定位。在实际开发中,结合BTrace的使用,可以...

    bTrace跟踪线程堆栈

    标题 "bTrace跟踪线程堆栈" 涉及到的是在Java开发中对线程堆栈进行监控和分析的技术,主要使用了开源工具bTrace。bTrace是一款强大的、无侵入式的Java运行时代码注入工具,允许开发者在运行中的Java应用上动态添加...

    btrace workbench

    【标题】"btrace workbench" 是一个专为Java开发者设计的强大工具,它与jvisualvm结合使用,提供了深入的应用程序性能分析能力。BTrace(Business Trace)是一种动态跟踪工具,允许开发者在运行时对Java应用程序进行...

    Btrace资源

    总的来说,Btrace是一个强大的Java调试和监控工具,通过这个资源包,你可以轻松地在运行中的Java应用程序上实施动态跟踪,提高问题定位和性能优化的效率。然而,为了充分利用这些工具,你需要学习Btrace的语法和使用...

    BTrace安装包 btrace-bin-1.3.11.3.zip + btrace-src-1.3.11.3.zip

    java监控调试工具虚拟机监控程序,利用BTrace可以在线监控java程序状态。 BTrace是一种安全,动态的Java跟踪工具。BTrace通过动态(字节码)检测正在运行的Java程序的类来工作。BTrace将跟踪操作插入到正在运行的...

    btrace.jar

    【btrace.jar】是一款强大的Java在线诊断工具,它允许开发者在不重启应用程序的情况下,实时地对Java程序进行动态追踪和分析。这个工具的核心价值在于它能够帮助我们在生产环境中无侵入地解决性能问题或者追踪特定的...

    btrace支持jdk1.6上运行的版本

    这个工具的独特之处在于,它不需要修改或重新编译源代码,而是通过向已运行的应用程序注入动态脚本来实现监控和调试。BTrace 支持 JDK 1.6 及以上版本,使得那些在较旧环境中运行的应用程序也能受益于这种强大的诊断...

    Btrace 官方zip包

    通过深入理解和熟练使用Btrace,开发者可以更有效地监控和调试Java应用,提升项目的稳定性和性能。尽管Btrace 在JDK 1.6时代就已经出现,但其核心理念和功能在现代Java开发中仍然具有很高的价值。

    BTrace自我总结测试代码

    BTrace 是一个强大的、安全的、动态的Java应用程序诊断工具,由Sun Microsystems(现已被Oracle收购)开发。它允许开发者在运行时对应用程序进行探查,而无需修改源代码或重启服务。BTrace 使用Java Agent技术,通过...

    BTrace监控远程服务器使用实例

    BTrace 是一个强大的、安全的、动态的Java应用程序诊断工具,它允许开发者在运行时对Java应用进行细粒度的监控和性能分析。BTrace利用了Java的动态代理机制(Java Agent)和ASM字节码库,能够在不中断程序运行的情况...

    btrace-bin.zip

    BTrace是一款强大的Java线上诊断和分析工具,它充分利用了Oracle HotSpot虚拟机的动态类替换功能,允许开发者在不重启应用程序的情况下,实时地添加或修改类的行为,特别是用于添加日志输出,以便于线上问题的调试。...

    btrace_extend-master

    BTrace是一款强大的动态代码分析工具,允许开发者在运行时对Java应用程序进行安全、精确的性能调试和诊断。 【描述】"btrace_extend-master" 指示这个压缩包解压后可以直接部署到服务器上,用于执行BTrace命令。这...

    btrace引导文件安装Btrace

    Btrace(Business Tracing for Java)是一种强大的动态追踪工具,专为Java应用程序设计。它允许开发者在不修改源代码的情况下,实时监控和分析应用程序的行为。Btrace利用Java代理(Java Agents)技术,在运行时对...

    BTrace测试

    BTrace是Sun Microsystems开发的一款强大的动态跟踪工具,它允许开发者在不修改生产代码的情况下,对Java应用程序进行诊断和性能监控。BTrace的全称是"Berkeley Trace",它基于字节码注入技术,可以实时地、安全地在...

Global site tag (gtag.js) - Google Analytics