BTrace使用小结
简介
BTrace是一个安全的JVM动态追踪工具,最初为原Sun公司Kenai项目下面的一个子项目。
典型的使用场景是,“我要查个问题,可那个方法没有打印入口参数和返回结果日志”,“我想看某个方法的执行耗时”,“我想查看某方法如System.GC()的调用栈”等等,这些都是BTrace可以小试牛刀的地方。它的优势是,直接attach应用JVM,不用重启应用进程,可比较快速方便地定位问题。
不错的教程
如果想简单学习一下BTrace,推荐几个不错的教程,建议先看看下面几篇文章:
Btrace入门到熟练小工完全指南 by 江南白衣,强烈建议先读它!
如何在生产环境使用Btrace进行调试 by 占小狼,点评同事,强烈建议读。
BTrace User's Guide,原官方文档
BTrace原理分析,进阶文章,日期比较早了,想深入了解的可以一看。
使用
下面是我学习BTrace的一点笔记和小结。不过还是先来个例子比较直观。
一个例子
一个简单的例子,我想查看某工程下这个方法的入参及返回值,但代码中没有打印方法返回结果,这个时候可以用BTrace试一下。
DemoView com.package.name.Demo.getDemoView(long id)
编写跟踪脚本MethodReturnTracing.java如下:
import static com.sun.btrace.BTraceUtils.println;
import static com.sun.btrace.BTraceUtils.str;
import com.sun.btrace.AnyType;
import com.sun.btrace.BTraceUtils;
import com.sun.btrace.annotations.BTrace;
import com.sun.btrace.annotations.Kind;
import com.sun.btrace.annotations.Location;
import com.sun.btrace.annotations.OnMethod;
import com.sun.btrace.annotations.Return;
import com.sun.btrace.annotations.Self;
/**
* 打印方法入参及返回值
*
* Created by zhouwei on 2017-6-21.
*/
@BTrace(unsafe = true) // 表示这是一个BTrace跟踪脚本,并启用unsafe模式(因为使用了BTraceUtils以外的方法,即String.valueOf(obj))
public class MethodReturnTracing {
@OnMethod(clazz = "com.package.name.Demo", // 类的全限定名
method = "getDemoView", // 方法名
location = @Location(Kind.RETURN)) // 表示跟踪某个类的某个方法,位置为方法返回处
public static void onMethodReturn(@Self Object self, long id, @Return AnyType result) { // @Return注解将上面被跟踪方法的返回值绑定到此探查方法的参数上
println(BTraceUtils.Time.timestamp("yyyy-MM-dd HH:mm:ss")); // 打印时间
println("method self: " + str(self));
println("method params: " + id); // 打印入参
println("method return: " + String.valueOf(result)); // 打印结果对象,因String.valueOf(obj)为外部方法,故需使用unsafe模式
println("=========================="); // 强烈建议加上,否则会因为输出缓冲看不到最新打印结果
}
}
将上面的跟踪脚本拷贝到测试服务器上,执行:
$ btrace -u 24801 MethodReturnTracing.java
2017-12-03 14:20:22
method self: com.package.name.Demo@6ae7d3b4
method params: 19261
method return: DemoView(id:19261, contactName:测试联系人, contactEmail:email, address:测试地址, ctime:1511871027, utime:1511871027, valid:1)
==========================
其中,-u表示使用BTrace的unsafe模式,24801为Java进程ID,MethodReturnTracing.java为BTrace跟踪脚本。下面是其跟踪日志,打印出了当前时间、方法入参和返回对象。
除脚本中的注释外,其它需要注意的点会在下面一一指出。
命令行启动
常用的三个命令:btrace用于将脚本attach应用Java进程,btracec用于编译脚本,btracer用于带着脚本启动Java进程并同时attach。
$ btrace <PID> <trace_script>
It will attach to the java application with the given PID and compile and submit the trace script.
$ btracec <trace_script>
It will compile the provided trace script.
$ btracer <compiled_script> <args to launch a java app>
It will start the specified java application with the btrace agent running and the script previously compiled by btracec loaded.
<trace_script>: Xxx.java,表示BTrace跟踪脚本。
<compiled_script>: Xxx.class,表示编译后的脚本。
常用注解介绍
下面是一些常用的注解,基本是从官网上或API文档上摘抄下来的,未作翻译。主要分两类:
用于注解探查方法(Action/probe Method),上面例子MethodReturnTracing.java中的
onMethodReturn即称为探查方法,作用通常是打印跟踪结果。用于注解探查方法的参数。例如上面例子MethodReturnTracing.java中的
@Return AnyType result,用于将被跟踪方法的返回值绑定到该探查方法的参数上。
注解探查方法(Action/probe Method Annotations)
@OnMethod(clazz=<cname_spec>[, method=<mname_spec>]? [, type=<signature>]? [, location=<location_spec>]?)
An action method annotated by this annotation is called when the matching method(s) reaches the specified location.
cname_spec = | + | /regex/
class_name is a fully qualified class name.
+class_name is a fully qualified class name prepended with +; means all subclasses and implementors of the prepended class name.
/regex/ is a standard regular expression used to identify the class names.
mname_spec = | /regex/
method_name is a simple method name (no signature or return type).
There is another way to abstractly specify traced class(es) and method(s). Traced classes and methods may be specified by annotation. For example, if the "clazz" attribute is specified as @javax.jws.WebService BTrace will instrument all classes that are annotated by the WebService annotation. Similarly, method level annotations may be used to specify methods abstractly.
@OnTimer
used to specify tracing actions that have to run periodically once every N milliseconds.
@OnError
used to specify actions that are run whenever any exception is thrown by tracing actions of some other probe.
BTrace method annotated by this annotation is called when any exception is thrown by any of the other BTrace action methods in the same BTrace class.
@OnExit
used to specify actions that are run when BTrace code calls "exit(int)" built-in function to finish the tracing "session".
@OnEvent
used to associate tracing methods with "external" events send by BTrace client.
@OnLowMemory
used to trace memory threshold exceed event.
@OnProbe
used to specify to avoid using implementation internal classes in BTrace scripts.
@Sampled
enables sampling for the annotated handler. To be used in conjunction with @OnMethod annotation.
其中,重点关注@OnMethod注解,最常用,用于跟踪某个方法。
clazz 指明要被跟踪的类的全限制名,支持正则表达式和继承,语法见说明。
method 指明要被跟踪的方法名,支持正则表达式。
type 指明要被跟踪的方法的签名。一般可以不声明,绝大部分情况下依靠clazz和method即可确定要跟踪的方法。
location 指明要跟踪的方法的位置。具体可见@Location注解的说明,例如@Location(Kind.RETURN)表示方法返回处,@Location(Kind.ENTRY)表示方法入口处。
注解探查方法的参数
这类注解的作用是将被跟踪方法的相关属性(关注点,如类名、方法名、方法入参、返回值、执行时间、抛出的异常等等)绑定到探查方法的参数上,然后在探查方法内作处理,如打印出来等等。例如@Duration用来捕获方法执行时间,@Return用于捕获方法返回值(它俩都只能用于@Location(Kind.RETURN)的location下),等等。分别摘录介绍如下。
@ProbeClassName
It is used to mark a probe method argument as the receiver of the probe target class name. Applicable only for OnMethod annotation. (对应@OnMethod的clazz的名字)
@ProbeMethodName
It is used to mark a probe method argument as the receiver of the probe target method name. Applicable only for OnMethod annotation. (对应@OnMethod的method的名字)
@Duration
It is used to mark a probe method argument as the receiver of the duration value. Applicable only for OnMethod annotation with Location value of Kind.RETURN or Kind.ERROR. (long, 纳秒;或用在where.AFTER)
@Return
Marks a method parameter as the one that should contain the return value. (applicable only for Kind.RETURN)
@Self
Marks a method parameter as the one that should contain this instance. (对应@OnMethod的clazz的对象)
@TargetInstance
It is used to mark a probe method argument as the receiver of called instance in Location = Kind.CALL. (对应@Location的clazz的对象,如果是静态方法,则返回null)
@TargetMethodOrField
It is used to mark a probe method argument as the receiver of called method name in Location = Kind.CALL. (对应@Location的method的名字)
一点经验
下面是我在使用BTrace的过程中积累的一点经验,希望对大家有用。
请在已经搭好的添加过依赖的maven工程中编写跟踪脚本!Git地址如下:btrace samples。其中com.sun.btrace.samples包中的代码为官方示例脚本,强烈建议看看;me.kopite.test下面为部分其它简单示例。
将btrace上传到服务器上,并设置环境变量,将btrace等命令加入命令行PATH中:
首先,在目标服务器(server)上执行(使用nc命令):
$ mkdir -p ~/zhouwei/btrace-bin-1.3.9 ; cd ~/zhouwei/btrace-bin-1.3.9 ; nc -l 8080 > btrace-bin-1.3.9.tgz ; tar zxvf btrace-bin-1.3.9.tgz ; export JAVA_HOME="/usr/local/java" ; export BTRACE_HOME=~/zhouwei/btrace-bin-1.3.9 ; export PATH=$BTRACE_HOME/bin:$PATH ; cd ~/zhouwei ; ll ; which btrace
如果服务器上已经有btrace包,则只需要执行上面后半部分的命令来设置环境变量即可:
$ export JAVA_HOME="/usr/local/java" ; export BTRACE_HOME=~/zhouwei/btrace-bin-1.3.9 ; export PATH=$BTRACE_HOME/bin:$PATH ; cd ~/zhouwei ; ll ; which btrace
然后,在本地机器上执行(serverIP即为目标服务器的IP地址):
$ nc $serverIP 8080 < ~/Downloads/btrace-bin-1.3.9.tgz
按自己的需要事先写好命令,即可在需要时快速上传和使用,节省时间提高效率。
由于服务器一般有端口访问限制,请使用8080附近的端口。
用于匹配方法入参或返回类型时,因嫌麻烦不想引入外部依赖(一般也没有必要),外部类型请用AnyType代替,而不是Object!因为你可能用Object来准确匹配方法返回参数或返回类型。例如上面例子MethodReturnTracing.java中的
@Return AnyType result。由于BTrace的安全和性能考虑,一般情况下不允许在探查方法中调用BTraceUtils以外的其它方法,但可使用unsafe模式。
例如使用String.valueOf()方法来打印对象(注意不要使用obj.toString(),因为对象可能是null!),这时需要使用非安全模式:
@BTrace(unsafe = true),并使用-u选项btrace -u <PID> <trace_script>来启动跟踪。例如使用
JSON.toJSONString()来打印对象(使用-cp选项来指明外部依赖的jar路径):
btrace -u -cp .:$(find /apps/xxx_service -type f -name "fastjson-*.jar" 2>/dev/null | head -1) <PID> <trace_script>具体参考
BTraceUtils.str(Object)方法说明,由非bootstrap class loader加载的对象不会调用对象的toString()方法,但List里面的对象可以打印出来(因为List对象是标准库里的类,由bootstrap class loader加载,且List的toString()方法调用了对象的toString()方法)。如何在thrift客户端拦截thrift接口调用?因为BTrace不支持拦截接口方法。通过查看调用栈,发现可以这么写:
clazz = "xxxThriftIface$Client",即拦截的类名clazz为接口名后面加$Client。打印输出有缓冲区延迟,故需要在探查方法的最后一行打印:
println("=================================");其它:
启动跟踪脚本时,请使用和启动Java进程相同的Linux账号,不然会因为权限问题而attach失败。
BTrace也可以用来跟踪匿名内部类的方法,只不过clazz对应的类名里面有个"$"符号,只要写对其类名即可。
对象构造函数的名字是
<init>,类构造器的名字是<clinit>。另一个和BTrace类似的Java诊断工具greys-anatomy,由阿里释出,感兴趣的也可以学习一下。
若报错"Port 2020 unavailable.",则使用
btrace -p 2021 ...来指定其它端口。Linux下已经有个命令也叫btrace,注意别用混了。
作者:lfckop
链接:https://www.jianshu.com/p/ee6b5c13c45b
來源:简书
BTrace使用小结的更多相关文章
- JVM系列十(虚拟机性能监控神器 - BTrace).
BTrace 是什么? BTrace 是一个动态安全的 Java 追踪工具,它通过向运行中的 Java 程序植入字节码文件,来对运行中的 Java 程序热更新,方便的获取程序运行时的数据信息,并且,保 ...
- 从零开始编写自己的C#框架(26)——小结
一直想写个总结,不过实在太忙了,所以一直拖啊拖啊,拖到现在,不过也好,有了这段时间的沉淀,发现自己又有了小小的进步.哈哈...... 原想框架开发的相关开发步骤.文档.代码.功能.部署等都简单的讲过了 ...
- Python自然语言处理工具小结
Python自然语言处理工具小结 作者:白宁超 2016年11月21日21:45:26 目录 [Python NLP]干货!详述Python NLTK下如何使用stanford NLP工具包(1) [ ...
- java单向加密算法小结(2)--MD5哈希算法
上一篇文章整理了Base64算法的相关知识,严格来说,Base64只能算是一种编码方式而非加密算法,这一篇要说的MD5,其实也不算是加密算法,而是一种哈希算法,即将目标文本转化为固定长度,不可逆的字符 ...
- iOS--->微信支付小结
iOS--->微信支付小结 说起支付,除了支付宝支付之外,微信支付也是我们三方支付中最重要的方式之一,承接上面总结的支付宝,接下来把微信支付也总结了一下 ***那么首先还是由公司去创建并申请使用 ...
- iOS 之UITextFiled/UITextView小结
一:编辑被键盘遮挡的问题 参考自:http://blog.csdn.net/windkisshao/article/details/21398521 1.自定方法 ,用于移动视图 -(void)mov ...
- K近邻法(KNN)原理小结
K近邻法(k-nearst neighbors,KNN)是一种很基本的机器学习方法了,在我们平常的生活中也会不自主的应用.比如,我们判断一个人的人品,只需要观察他来往最密切的几个人的人品好坏就可以得出 ...
- scikit-learn随机森林调参小结
在Bagging与随机森林算法原理小结中,我们对随机森林(Random Forest, 以下简称RF)的原理做了总结.本文就从实践的角度对RF做一个总结.重点讲述scikit-learn中RF的调参注 ...
- Bagging与随机森林算法原理小结
在集成学习原理小结中,我们讲到了集成学习有两个流派,一个是boosting派系,它的特点是各个弱学习器之间有依赖关系.另一种是bagging流派,它的特点是各个弱学习器之间没有依赖关系,可以并行拟合. ...
随机推荐
- 100以内的质数(for和if)
- QA CodeDiff做什么?什么时间做?
一.QA CodeDiff都在做什么 1.防止开发合并代码出错.要不删除了别人的要不删除了自己的,比如代码冲突后简单的选择使用他人或自己: 2.开发夹杂私货,在不通知QA的情况下私自修改bug或增加功 ...
- OCM_第七天课程:Section3 —》数据库可用性
注:本文为原著(其内容来自 腾科教育培训课堂).阅读本文注意事项如下: 1:所有文章的转载请标注本文出处. 2:本文非本人不得用于商业用途.违者将承当相应法律责任. 3:该系列文章目录列表: 一:&l ...
- InnoDB的关键特性-插入缓存,两次写,自适应hash索引
InnoDB存储引擎的关键特性包括插入缓冲.两次写(double write).自适应哈希索引(adaptive hash index).这些特性为InnoDB存储引擎带来了更好的性能和更高的可靠性. ...
- python 全栈开发,Day65(MySQL练习题,参考答案)
一.MySQL练习题 一.表关系 请创建如下表,并创建相关约束 二.操作表 1.自行创建测试数据 2.查询“生物”课程比“物理”课程成绩高的所有学生的学号.ps:针对的是自己的生物成绩比物理成绩高,再 ...
- python 全栈开发,Day51(常用内置对象,函数,伪数组 arguments,关于DOM的事件操作,DOM介绍)
昨日内容回顾 1.三种引入方式 1.行内js <div onclick = 'add(3,4)'></div> //声明一个函数 function add(a,b){ } 2. ...
- MyEclipse中把JSP默认编码改为UTF-8
在MyEclispe中创建Jsp页面,Jsp页面的默认编码是“ISO-8859-1”,如下图所示: 在这种编码下编写中文是没有办法保存Jsp页面的,会出现如下的错误提示: 因此可以设置Jsp默认的编码 ...
- 《剑指offer》-左旋转字符串
汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果.对于一个给定的字符序列S,请你把其循环左移K位后的序列输出.例如,字符序列S="abc ...
- Codeforces Round #319 (Div. 2) D - Invariance of Tree
Invariance of Tree 题目大意:给你一个有1-n组成的序列p,让你构造一棵树,如果节点a和b之间有一条边,则p[a]和p[b]之间也有一条边. 思路:没啥思路,看了题解菜爆. 我们可以 ...
- Python 时间获取
摘自:http://www.jb51.net/article/91365.htm 摘自:https://www.cnblogs.com/liuq/p/6211005.html 一.在python中,除 ...