使用jvisualvm.exe 的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. 示例代码

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

Btracetest.java代码  

  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. }

Counter.java代码  

  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()方法参数值和返回值。

Java代码  

  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。

Java代码  

  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方法执行时间。

Java代码  

  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()次数。

Java代码  

  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

原文:http://learnworld.iteye.com/blog/1402763

时间: 2024-10-06 17:29:44

使用jvisualvm.exe 的Btrace插件介绍/使用教程的相关文章

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

之前提到使用命令行的方式执行btrace监控,其实jdk提供更好的方式监控应用程序. 我们可以使用jvisualvm.exe加插件的方式监控,这样更加方便. 1.在jvisualvm.exe安装btrace插件 在这里选择Btrace 插件,由于我已经安装 ,这就就不能在选择了. 2.使用插件 在需要监控的应用邮件点击. 这样就打开了btrace插件. 在上面的框中编辑监控代码,在classpath 中加入 btrace相关的jar包,点击start就可以开始监控了. 点开始时插件会检查代码是否

Notepad++前端开发常用插件介绍

Notepad++前端开发常用插件介绍 Notepad++除了自身的功能强大之外,更是有许多非常的优秀的插件,下面就总结一下前端开发过程一些比较常用的插件. Emmet Emmet的前身是Zen Coding,一款使用仿CSS选择器的语法来快速开发HTML和CSS的插件,是前端开发神器.它无视了编辑器的自动提示和自动完成,秒杀了你自定义的各种快捷键或者 AHK 的热字符串,以智能简洁高效的缩短输入,带给你超快速地书写各种复杂而枯燥的 HTML 和 CSS 代码的体验.现在可以在Notepad++

自制MVC框架CRUD操作、列表、分页显示插件介绍

这里涉及到的操作都是引用自Stephen.DALService数据层.数据访问层实现方式在后文中我会仔细的说明,先说明一下数据操作集成的插件. 1).InsertAttribute 用于插入记录. 状态返回值:假定hashtable传递变量名的是context ,那么返回值可通过context[InsertAttribute.ValueKey]得到,推荐返回的是插入的主键ID值,当然这个是由数据层设定的. 有以下属性可进行设置: 属性名 作用 默认值 选项说明 其它说明 Key 映射路径.格式如

jQuery Fancybox插件介绍

下面介绍一款jquery图片播放插件叫Fancybox,项目主页地址:http://fancybox.net/ Fancybox的特点如下: 1.可以支持图片.html文本.flash动画.iframe以及ajax的支持 2.可以自定义播放器的CSS样式 3.可以以组的形式进行播放,导航的按钮(上一项,下一项) 4.如果将鼠标滚动插件(mouse wheel plugin)包含进来的话Fancybox还能支持鼠标滚轮滚动来翻阅图片 5.Fancybox播放器支持投影,更有立体的感觉 Fancyb

Gulp构建前端自动化工作流之:常用插件介绍及使用

在对Gulp有了一个初步的了解之后,我们开始构建一个较为完整的Gulp开发环境. 本文主要分为6个段落: 1. 构建项目目录结构(Directory Structure Build) 2. 插件介绍及使用方法(Tasks and dependencies) 3. 扩展优化(Extend & Optimize Task) 4. 其他插件介绍(Other plug-ins) 5. 匹配规则(Match Files) 6. 注意事项(Attention) 关于Gulp的入门介绍及安装方法,可先去 <

【转】LiveWriter插入高亮代码插件介绍 基于SyntaxHighighter

转自:http://www.cnblogs.com/yaoshiyou/archive/2009/11/25/1610901.html 插件介绍 辛苦了两人小时写日志不小心浏览器崩溃了,发誓以后一定记得用Word先写好. 将Word 中的内容copy编辑器中,就是不大对劲,最惨的就图片,根本就没有. 在记事本中写内容,代码图片一张张处理. 打开网站—>输入用户名->输入密码->输入验证码->正在进入->用户名或密码错误->重输-正在进入->验证码不正确->…

Grafana、collectd 和 InfluxDB 打造酷炫监控系统(四)常用插件介绍和自定义数据篇

一.常用插件介绍 获取指定端口的连接状态ESTABLISHED.CLOSE_WAIT.LISTEN等 tcpconns: <Plugin tcpconns> ListeningPorts false LocalPort "80" RemotePort "80" </Plugin> 获取Nginx的状态 nginx: <Plugin nginx> URL "http://test.tt.com/NginxStatus&qu

CSDN开源夏令营 基于Compiz的switcher插件设计与实现之compiz特效插件介绍及特效实现

compiz自带的特效插件不够多,也不够强大,为了更好的体验compiz的特效,我们可以安装特效插件,在终端输入命令:sudo apt-get install compiz-plugins就可以下载特效插件安装了. 一.安装compiz特效插件 在此过程中可能会出现一些问题,比如说依赖问题,我们需要把源更新一下.对于更新源,我们需要注意以下几点: 1.设置软件更新 注意:这里要选主服务器 2.更新源 在终端输入命令:sudo apt-get update来更新源,一般情况下,这样是可以的,但是,

从零开始编写自己的C#框架(6)——SubSonic3.0插件介绍(附源码)

原文:从零开始编写自己的C#框架(6)--SubSonic3.0插件介绍(附源码) 前面几章主要是概念性的东西为主,向初学者们介绍项目开始前的一些知识与内容,从本章开始将会进入实操阶段,希望跟着本系统学习的朋友认真按说明做好每一步操作(对于代码最好是直接照着文档内容在你的IDE中打一次出来,而不是使用复制粘贴),这样对你理解后面的章节会有较好的帮助,如果你对我这种书写方式有什么建议或支持,也希望在评论中留言,谢谢你的支持. SubSonic3.0简介 SubSonic是Rob Conery用c#