一、背景 
       在生产环境中可能经常遇到各种问题,定位问题需要获取程序运行时的数据信息,如方法参数、返回值、全局变量、堆栈信息等。为了获取这些数据信息,我们可以通过改写代码,增加日志信息的打印,再发布到生产环境。通过这种方式,一方面将增大定位问题的成本和周期,对于紧急问题无法做到及时响应;另一方面重新部署后环境可能已被破坏,很难重新问题的场景。

二、BTrace功能 
       BTrace天生就为解决这类问题而来,它可以动态地跟踪java运行程序。通过hotswap技术,动态将跟踪字节码注入到运行类中,对运行代码侵入较小,对性能上的影响可以忽略不计。 
       BTrace在使用上有很多限制条件,如不能创建对象、数组、抛出和捕获异常、循环等,具体限制条件参考用户文档中的BTrace Restrictions。用户文档地址: http://kenai.com/projects/btrace/pages/UserGuide。 
       根据官方声明,不当地使用btrace可能导致jvm崩溃,如BTrace使用错误的.class文件,Hotspot JVM自身存在的hotswap bug等。可以先在本地验证BTrace脚本的正确性,再传到生产环境中定位问题。

三、安装步骤 
1. 下载安装压缩包,最新版本的是1.2.1,下载地址: http://kenai.com/projects/btrace/downloads/directory/releases。 
2. 解压缩,命令脚本放在bin目录中。 
3. 设置脚本环境变量。 
4. 增加脚本可执行权限。

四、使用方法 
BTrace主要包含btracec和btrace两个命令编译和启动BTrace脚本: 
1. btrace 
功能: 用于运行BTrace跟踪程序。 
命令格式: 
btrace [-I <include-path>] [-p <port>] [-cp <classpath>] <pid> <btrace-script> [<args>] 
示例: 
btrace -cp build/  1200 AllCalls1.java 
参数含义: 
include-path指定头文件的路径,用于脚本预处理功能,可选; 
port指定BTrace agent的服务端监听端口号,用来监听clients,默认为2020,可选; 
classpath用来指定类加载路径,默认为当前路径,可选; 
pid表示进程号,可通过jps命令获取; 
btrace-script即为BTrace脚本;btrace脚本如果以.java结尾,会先编译再提交执行。可使用btracec命令对脚本进行预编译。 
args是BTrace脚本可选参数,在脚本中可通过"$"和"$length"获取参数信息。

2. btracec 
功能: 用于预编译BTrace脚本,用于在编译时期验证脚本正确性。 
btracec [-I <include-path>] [-cp <classpath>] [-d <directory>] <one-or-more-BTrace-.java-files> 
参数意义同btrace命令一致,directory表示编译结果输出目录。

3. btracer 
功能: btracer命令同时启动应用程序和BTrace脚本,即在应用程序启动过程中使用BTrace脚本。而btrace命令针对已运行程序执行BTrace脚本。 
命令格式: 
btracer <pre-compiled-btrace.class> <application-main-class> <application-args> 
参数说明: 
pre-compiled-btrace.class表示经过btracec编译后的BTrace脚本。 
application-main-class表示应用程序代码; 
application-args表示应用程序参数。 
该命令的等价写法为: 
java -javaagent:btrace-agent.jar=script=<pre-compiled-btrace-script1>[,<pre-compiled-btrace-script1>]* <MainClass> <AppArguments>

4. jvisualvm插件 
BTrace提供了jvisualvm插件,强烈推荐在jvisualvm中编写和测试BTrace脚本,启动、关闭、发送事件、增加classpath都非常方便。 

五、BTrace实战 
1. 示例代码 
示例代码定义了Counter计数器,有一个add()方法,每次增加随机值,总数保存在totalCount属性中。

  1. package com.learnworld;
  2. import java.util.Random;
  3. public class BTraceTest {
  4. public static void main(String[] args) throws Exception {
  5. Random random = new Random();
  6. // 计数器
  7. Counter counter = new Counter();
  8. while (true) {
  9. // 每次增加随机值
  10. counter.add(random.nextInt(10));
  11. Thread.sleep(1000);
  12. }
  13. }
  14. }
  1. package com.learnworld;
  2. public class Counter {
  3. // 总数
  4. private static int totalCount = 0;
  5. public int add(int num) throws Exception {
  6. totalCount += num;
  7. sleep();
  8. return totalCount;
  9. }
  10. public void sleep() throws Exception {
  11. Thread.sleep(1000);
  12. }
  13. }

2. 常见使用场景 
下面通过几个常见使用场景演示如何使用BTrace脚本。

1) 获取add()方法参数值和返回值。

  1. import com.sun.btrace.annotations.*;
  2. import static com.sun.btrace.BTraceUtils.*;
  3. @BTrace
  4. public class TracingScript {
  5. @OnMethod(
  6. clazz="com.learnworld.Counter",
  7. method="add",
  8. location=@Location(Kind.RETURN)
  9. )
  10. public static void traceExecute(int num,@Return int result){
  11. println("====== ");
  12. println(strcat("parameter num: ",str(num)));
  13. println(strcat("return value:",str(result)));
  14. }
  15. }

2) 定时获取Counter类的属性值totalCount。

  1. import com.sun.btrace.annotations.*;
  2. import static com.sun.btrace.BTraceUtils.*;
  3. @BTrace
  4. public class TracingScript {
  5. private static Object totalCount = 0;
  6. @OnMethod(
  7. clazz="com.learnworld.Counter",
  8. method="add",
  9. location=@Location(Kind.RETURN)
  10. )
  11. public static void traceExecute(@Self com.learnworld.Counter counter){
  12. totalCount = get(field("com.learnworld.Counter","totalCount"), counter);
  13. }
  14. @OnTimer(1000)
  15. public static void print(){
  16. println("====== ");
  17. println(strcat("totalCount: ",str(totalCount)));
  18. }
  19. }

3) 获取add方法执行时间。

  1. import com.sun.btrace.annotations.*;
  2. import static com.sun.btrace.BTraceUtils.*;
  3. @BTrace
  4. public class TracingScript {
  5. @TLS private static long startTime = 0;
  6. @OnMethod(
  7. clazz="com.learnworld.Counter",
  8. method="add"
  9. )
  10. public static void startExecute(){
  11. startTime = timeNanos();
  12. }
  13. @OnMethod(
  14. clazz="com.learnworld.Counter",
  15. method="add",
  16. location=@Location(Kind.RETURN)
  17. )
  18. public static void endExecute(@Duration long duration){
  19. long time = timeNanos() - startTime;
  20. println(strcat("execute time(nanos): ", str(time)));
  21. println(strcat("duration(nanos): ", str(duration)));
  22. }
  23. }

4) 获取add()方法调用方法sleep()次数。

  1. import com.sun.btrace.annotations.*;
  2. import static com.sun.btrace.BTraceUtils.*;
  3. @BTrace
  4. public class TracingScript {
  5. private static long count;
  6. @OnMethod(
  7. clazz="/.*/",
  8. method="add",
  9. location=@Location(value=Kind.CALL, clazz="/.*/", method="sleep")
  10. )
  11. public static void traceExecute(@ProbeClassName String pcm, @ProbeMethodName String pmn,
  12. @TargetInstance Object instance,  @TargetMethodOrField String method){
  13. println("====== ");
  14. println(strcat("ProbeClassName: ",pcm));
  15. println(strcat("ProbeMethodName: ",pmn));
  16. println(strcat("TargetInstance: ",str(classOf(instance))));
  17. println(strcat("TargetMethodOrField : ",str(method)));
  18. count++;
  19. }
  20. @OnEvent
  21. public static void getCount(){
  22. println(strcat("count: ", str(count)));
  23. }
  24. }

六、参考文档 
1. userGuide: http://kenai.com/projects/btrace/pages/UserGuide 
2. JAVA doc:  http://btrace.kenai.com/javadoc/1.2/index.html 
3. BTrace用户手册<译>,http://macrochen.iteye.com/blog/838920 
4. btrace使用简介,http://rdc.taobao.com/team/jm/archives/509 
5. btrace记忆,http://agapple.iteye.com/blog/962119 
6. btrace一些你不知道的事(源码入手),http://agapple.iteye.com/blog/1005918 

BTrace使用总结的更多相关文章

  1. java性能调优及问题追踪--Btrace的使用

    在生产环境中经常遇到格式各样的问题,如OOM或者莫名其妙的进程死掉.一般情况下是通过修改程序,添加打印日志:然后重新发布程序来完成.然而,这不仅麻烦,而且带来很多不可控的因素.有没有一种方式,在不修改 ...

  2. btrace使用

    btrace使用 目录btracee是btrace的解压目录 btrace/btrace是btrace的项目工程 root@ubuntu:/usr/local/bogon/btrace# tree b ...

  3. 使用jvisualvm.exe 的Btrace插件介绍/使用教程

    一.背景        在生产环境中可能经常遇到各种问题,定位问题需要获取程序运行时的数据信息,如方法参数.返回值.全局变量.堆栈信息等.为了获取这些数据信息,我们可以 通过改写代码,增加日志信息的打 ...

  4. BTrace入门教程

    bin版:https://kenai.com/projects/btrace/downloads/directory/releases 源码:https://github.com/btraceio/b ...

  5. 让VisualVM+BTrace进入unsafe mode

    让VisualVM+BTrace进入unsafe mode http://kenai.com/projects/btrace/pages/UserGuide BTrace很强大,但有很多安全限制,比如 ...

  6. 使用jvisualvm.exe 的Btrace插件监控应用程序

    之前提到使用命令行的方式执行btrace监控,其实jdk提供更好的方式监控应用程序. 我们可以使用jvisualvm.exe加插件的方式监控,这样更加方便. 1.在jvisualvm.exe安装btr ...

  7. 使用BTRACE定位系统中慢的问题

    在访问页面请求的时候,如果系统执行效率低,我们怎样才能定位到这些页面请求呢?   java 有一个十分有效的动态跟踪工具-btrace 网址:https://kenai.com/projects/bt ...

  8. Java BTrace实战(1)--BTrace的入门和使用

    前言: 对线上的java服务, 往往采用日志进行问题处理和分析. 倘若日志缺乏相关的信息时, 那又该如何处理? 远程调试会影响服务的正常工作, 修改代码重新部署的方案其实时性和灵活性难以保证(线上服务 ...

  9. Btrace入门到熟练小工完全指南

    BTrace是神器,每一个需要每天解决线上问题,但完全不用BTrace的Java工程师,都是可疑的. BTrace的最大好处,是可以通过自己编写的脚本,获取应用的一切调用信息.而不需要不断地修改代码, ...

  10. btrace 实践笔记

    btrace简介:     btrace 是一个使用在JAVA平台上面的,安全的,动态跟踪工具.它一般用于动态跟踪正在运行的jAVA程序.     使用说明在这里.下载地址在这里.     下载的时候 ...

随机推荐

  1. C# string LastIndexOf()

    IndexOf(“FindText",start,len) 中的Start和Len是从左往右数的 LastIndexOf(“FindText",start,len)中的则是从右往左 ...

  2. c++ 标准委员会网址

    c++ 标准委员会网址: http://www.open-std.org/ C++11 文档网址: http://www.open-std.org/jtc1/sc22/wg21/docs/papers ...

  3. 限制sqlserver最大内存后无法连接-EXEC sp_configure max server memory

    在sql server 中设置了过小的 "max server memory"最大内存后,sqlserver可启动,但是无法连接. 网络上流行的"sqlserver 内存 ...

  4. Wordpress 网站搭建及性能监控方法详解!

    前言 说到 Wordpress,大家往往想到的是博客,其实,如今的 WordPress 已经成为全球使用量最多的开源 CMS 系统.并且,如果你有一定的技术基础稍加改动,就可以搭建出新闻网站.企业网站 ...

  5. CISCO2691的OSPF点对点密文测评测试

    都差不多,粘一个文件就能说明问题了. Router#show run Building configuration... Current configuration : bytes ! version ...

  6. apache整合tomcat部署集群

    近日,由于公司项目需要,所以学习了apache整合tomcat以及集群的一些知识. 所以做下笔记日后回顾可以用到. apache只有处理静态事物的能力, 而tomcat的强项就是处理动态的请求,所以a ...

  7. [mock]10月11日

    第二次mock.出的题是,假设有一个地区不能使用7,都用之后的数字代替,比如8代表7,18代表16(中间有7和17).那么给出一个这个地区的数X,求普通地区的数Y.首先是找规律,发现其实就是找给出的数 ...

  8. delphi非IE内核浏览器控件TEmbeddedChrome下载|TEmbeddedChrome代码

    下载地址: 点击下载 代码示例: 在TForm的oncreate方法中写入一些代码 procedure TForm1.FormCreate(Sender: TObject); begin Chromi ...

  9. MySQL源码之mysqld启动

    启动mysqld,并进入listen阶段   函数调用栈: mysqld_main():        my_init();初始化变量,锁,错误串      my_thread_global_init ...

  10. 关于启动Visual Studio 2010 旗舰版的几个错误的解决方法。

    关于启动Visual Studio 2010 旗舰版的几个错误的解决方法.亲测. 重做系统之后,今天是第一次打开Visual Studio 2010 旗舰版码代码,结果遇到几个弹出的对话框,现在与大家 ...