BTrace使用总结

摘要:
BTrace在使用上有很多限制条件,如不能创建对象、数组、抛出和捕获异常、循环等,具体限制条件参考用户文档中的BTraceRestrictions。根据官方声明,不当地使用btrace可能导致jvm崩溃,如BTrace使用错误的.class文件,HotspotJVM自身存在的hotswapbug等。可以先在本地验证BTrace脚本的正确性,再传到生产环境中定位问题。可使用btracec命令对脚本进行预编译。而btrace命令针对已运行程序执行BTrace脚本。

一、背景
在生产环境中可能经常遇到各种问题,定位问题需要获取程序运行时的数据信息,如方法参数、返回值、全局变量、堆栈信息等。为了获取这些数据信息,我们可以通过改写代码,增加日志信息的打印,再发布到生产环境。通过这种方式,一方面将增大定位问题的成本和周期,对于紧急问题无法做到及时响应;另一方面重新部署后环境可能已被破坏,很难重新问题的场景。
二、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张
五、BTrace实战
1. 示例代码
示例代码定义了Counter计数器,有一个add()方法,每次增加随机值,总数保存在totalCount属性中。
Btracetest.java代码收藏代码
  1. packagecom.learnworld;
  2. importjava.util.Random;
  3. publicclassBTraceTest{
  4. publicstaticvoidmain(String[]args)throwsException{
  5. Randomrandom=newRandom();
  6. //计数器
  7. Countercounter=newCounter();
  8. while(true){
  9. //每次增加随机值
  10. counter.add(random.nextInt(10));
  11. Thread.sleep(1000);
  12. }
  13. }
  14. }

Counter.java代码收藏代码
  1. packagecom.learnworld;
  2. publicclassCounter{
  3. //总数
  4. privatestaticinttotalCount=0;
  5. publicintadd(intnum)throwsException{
  6. totalCount+=num;
  7. sleep();
  8. returntotalCount;
  9. }
  10. publicvoidsleep()throwsException{
  11. Thread.sleep(1000);
  12. }
  13. }

2. 常见使用场景
下面通过几个常见使用场景演示如何使用BTrace脚本。
1) 获取add()方法参数值和返回值。
Java代码收藏代码
  1. importcom.sun.btrace.annotations.*;
  2. importstaticcom.sun.btrace.BTraceUtils.*;
  3. @BTrace
  4. publicclassTracingScript{
  5. @OnMethod(
  6. clazz="com.learnworld.Counter",
  7. method="add",
  8. location=@Location(Kind.RETURN)
  9. )
  10. publicstaticvoidtraceExecute(intnum,@Returnintresult){
  11. println("======");
  12. println(strcat("parameternum:",str(num)));
  13. println(strcat("returnvalue:",str(result)));
  14. }
  15. }

2) 定时获取Counter类的属性值totalCount。
Java代码收藏代码
  1. importcom.sun.btrace.annotations.*;
  2. importstaticcom.sun.btrace.BTraceUtils.*;
  3. @BTrace
  4. publicclassTracingScript{
  5. privatestaticObjecttotalCount=0;
  6. @OnMethod(
  7. clazz="com.learnworld.Counter",
  8. method="add",
  9. location=@Location(Kind.RETURN)
  10. )
  11. publicstaticvoidtraceExecute(@Selfcom.learnworld.Countercounter){
  12. totalCount=get(field("com.learnworld.Counter","totalCount"),counter);
  13. }
  14. @OnTimer(1000)
  15. publicstaticvoidprint(){
  16. println("======");
  17. println(strcat("totalCount:",str(totalCount)));
  18. }
  19. }

3) 获取add方法执行时间。
Java代码收藏代码
  1. importcom.sun.btrace.annotations.*;
  2. importstaticcom.sun.btrace.BTraceUtils.*;
  3. @BTrace
  4. publicclassTracingScript{
  5. @TLSprivatestaticlongstartTime=0;
  6. @OnMethod(
  7. clazz="com.learnworld.Counter",
  8. method="add"
  9. )
  10. publicstaticvoidstartExecute(){
  11. startTime=timeNanos();
  12. }
  13. @OnMethod(
  14. clazz="com.learnworld.Counter",
  15. method="add",
  16. location=@Location(Kind.RETURN)
  17. )
  18. publicstaticvoidendExecute(@Durationlongduration){
  19. longtime=timeNanos()-startTime;
  20. println(strcat("executetime(nanos):",str(time)));
  21. println(strcat("duration(nanos):",str(duration)));
  22. }
  23. }

4) 获取add()方法调用方法sleep()次数。
Java代码收藏代码
  1. importcom.sun.btrace.annotations.*;
  2. importstaticcom.sun.btrace.BTraceUtils.*;
  3. @BTrace
  4. publicclassTracingScript{
  5. privatestaticlongcount;
  6. @OnMethod(
  7. clazz="/.*/",
  8. method="add",
  9. location=@Location(value=Kind.CALL,clazz="/.*/",method="sleep")
  10. )
  11. publicstaticvoidtraceExecute(@ProbeClassNameStringpcm,@ProbeMethodNameStringpmn,
  12. @TargetInstanceObjectinstance,@TargetMethodOrFieldStringmethod){
  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. publicstaticvoidgetCount(){
  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使用总结》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇zookeeper(五) curator 锁机制Tomcat服务器下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

VisualVM初次使用BTrace功能方法步骤

  前提安装好了VisualVM,并且安装了插件BTrace(期间出现了一个小问题,那就是标签里面怎么找不到BTrace标签,后面经过实践在VisualVM的application里找到要调试的进程,然后通过右击那个进程即可找到BeTrace这个标签,来进行coding)       1、我这在esclipse里面的演示demo coding如下: 1...

Oracle 多行记录合并/连接/聚合字符串的几种方法

怎么合并多行记录的字符串,一直是oracle新手喜欢问的SQL问题之一,关于这个问题的帖子我看过不下30个了,现在就对这个问题,进行一个总结。-什么是合并多行字符串(连接字符串)呢,例如: 1 SQL> desc test; 2 Name Type Nullable Default Comments 3 ------- -------...