在生产环境中经常遇到格式各样的问题,如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);}
}
package com.vmtools;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

/* BTrace Script Template */
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;//定时获取Counter类的属性值totalCount。
@BTrace
public class TracingScript {private static Object totalCount=0;/* put your code here */@OnMethod(clazz="com.vmtools.Counter",method="add",location=@Location(Kind.RETURN))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方法执行时间

/* BTrace Script Template */
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;//获取add方法执行时间
@BTrace
public class TracingScript {@TLS private static long startTime = 0;/* put your code here */@OnMethod(clazz="com.vmtools.Counter",method="add")public static void func(@Self com.vmtools.Counter counter) {startTime = timeNanos();}@OnMethod(clazz="com.vmtools.Counter",method="add",location=@Location(Kind.RETURN))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.jianshu.com/p/dbb3a8b5c92f
  • http://www.cnblogs.com/langtianya/p/4444025.html

java性能调优及问题追踪--Btrace的使用相关推荐

  1. 为什么对 Java 性能调优最后都像在调 you?

    不知道你有没有发现,优化Java,或者任何其他语言的代码性能经常被当做是一种暗黑艺术. 性能分析有种神秘感.画面类似是这样的:一个「黑客」经过多年练就的手艺,能够快速深入了解某个系统,并提出神奇的解决 ...

  2. 11 个简练的 Java 性能调优技巧

    转载自 11 个简练的 Java 性能调优技巧 想要让你的项目一直高性能运作吗?以下有一些技巧你可以拿去消除缓存瓶颈,还有一些其他的性能调优建议. 大多数开发者认为性能优化是一个复杂的话题,它需要大量 ...

  3. java 性能调优_Java性能调优调查结果(第四部分)

    java 性能调优 这是本系列中的最后一篇文章,我们将分析我们在2014年10月进行的Java Performance Tuning Survey的结果.如果您尚未阅读第一篇文章,建议您首先阅读以下内 ...

  4. java 性能调优_Java性能调优调查结果(第三部分)

    java 性能调优 这是本系列文章的第三篇,我们将分析2014年10月进行的调查的结果.如果您尚未这样做,我建议从本系列的前两篇文章开始: 问题严重性分析和监视域分析 . 这篇文章着重于故障排除/根本 ...

  5. java 性能调优_Java性能调优调查结果(第二部分)

    java 性能调优 这是系列文章的第二篇,我们将分析2014年10月进行的性能调整调查的结果.如果您尚未阅读第一部分,我们建议从此处开始 . 第二部分将重点监视Java应用程序的性能问题. 特别是,我 ...

  6. java 性能调优_Java性能调优调查结果(第一部分)

    java 性能调优 我们在2014年10月进行了Java性能调优调查.该调查的主要目的是收集对Java性能世界的见解,以改善Plumbr产品. 但是,我们也很高兴与您分享有趣的结果. 我们收集的数据为 ...

  7. java必读书籍_最佳5本Java性能调优书籍–精选,必读

    java必读书籍 为什么Java开发人员应该阅读有关性能调优的书? 当我很久以前第一次面对这个问题时,我以为以后会做,但是我很长一段时间都没有回过头来. 仅当我在用Java编写的任务关键型服务器端财务 ...

  8. Java性能调优:充分利用垃圾收集器

    JVM背后发生了什么,垃圾回收如何影响Java性能? 性能调优世界是一个危险的地方,一个JVM标志失衡,事情很快就会变得繁琐. 因此 ,我们决定求助于Java性能调优专家, 单调 JVM探查器mjpr ...

  9. Java性能调优调查结果(第一部分)

    我们在2014年10月进行了Java性能调优调查.该调查的主要目的是收集对Java性能世界的见解,以改进Plumbr产品. 但是,我们也很高兴与您分享有趣的结果. 我们收集的数据为进行冗长的分析提供了 ...

最新文章

  1. Python大法之抛 异常
  2. Thinkphp的知识内容
  3. 特征工程tf-idf_特征工程-保留和删除的内容
  4. 最新版Spring Cloud Alibaba微服务架构-Openfeign服务调用篇
  5. 【Guava】Guava Cache的refresh和expire刷新机制
  6. js 匿名函数_javascript:函数的使用
  7. UNIX环境高级编程(第2版)第11-17章
  8. linux 使用秘钥认证,linux 密钥验证登录
  9. 静态HTML个人博客主页 简单个人网页设计作业 DW个人网站模板下载 大学生简单个人网页作品代码 个人网页制作 学生个人网页设计作业
  10. Renascence架构介绍——目录
  11. [初学笔记] tic toc 计算程序运行时间
  12. Java响应式编程基础-响应式流
  13. Browsing HDFS报错
  14. Asta:是什么终结了我的鸽王生涯?Go 1.13 发布!
  15. 教你制作第一个C++游戏!#1 引入
  16. 洛谷P1851 好朋友
  17. 拼多多开店怎么提高点击率?天创速盈提出应对措施
  18. java+mysql简单实现点赞评论转发帖子
  19. SpringCloud Edgware.SR3版本-Ribbon的timeout设置
  20. 等边三角形的绘制。使用turtle库中的turtle.fd()函数和turtle.seth()函数绘制一个等边三角形。

热门文章

  1. Linux文件系统与日志分析(inode、inode节点耗尽故障处理、文件备份和恢复、日志文件管理)
  2. mac开启64位内核
  3. 方舟编译器服务器端Java怎么用_方舟编译器可以运行Hello World了!
  4. flash activex java_Adobe flash player ActiveX和NPAPI和PPAPI 这三个软件有什么区别?
  5. cdn厂商 同兴万点_同兴万点:TXNetworks和CDNetworks让我们傻傻分不清
  6. 用户管理系统_【20201204】做个用户管理系统(18)——注册功能的实现(三)...
  7. c语言获取按键痕迹,c语言获得键盘的按键
  8. python csv读取数据 去掉标题-Python读csv文件去掉一列后再写入新的文件实例
  9. java中properties作用,java中Properties有什么用,举例说明?
  10. android studio中error,ERROR在Android Studio中