最近排查线上OOM的异常时用到一个强大的动态跟踪分析工具BTrace,于是花了点时间研究了下用法,这里的内容基本是对官方说明进行的翻译,顺便加了点心得.
BTrace介绍
BTrace是一个Java的动态跟踪工具,BTrace的工作的基本原理是把跟踪的代码动态替换到被跟踪的Java程序内,其实现机制是Sun Attach API + BTrace脚本解析引擎 + Objectweb ASM + JDK6 Instumentation,项目主页是在这里,用户指南点击这里.
安装BTrace
BTrace的安装非常简单,首先你需要下载BTrace,最新的版本是1.2.2,然后解压至任意目录,设置好BTRACE_HOME后将bin目录加入至环境变量PATH中即可.
使用BTrace
BTrace的使用也是非常简单,使用如下命令即可
1
|
btrace
<
pid
>
Test
.java
|
其中,pid为你想要跟踪的Java程序的pid,Test.java为BTrace的脚本,下面我们就来看一个简单的BTrace脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import
com
.
sun
.
btrace
.
annotations
.
*
;
import
static
com
.
sun
.
btrace
.
BTraceUtils
.
*
;
@BTrace
public
class
HelloWorld
{
@OnMethod
(
clazz
=
"java.lang.Thread"
,
method
=
"start"
)
public
static
void
func
(
)
{
println
(
"start a thread!"
)
;
}
}
|
简单解释下这里面的意思,@OnMethod告诉Btrace解析引擎需要代理的类和方法,这个例子的作用是当java.lang.Thread类的任意一个对象调用start方法后调用func方法.
BTrace重要概念与局限性
虽然BTrace很强大,但Btrace脚本就是一个普通的用@Btrace注解的Java类,其中包含一个或多个public static void修饰的方法,为了保证对目标程序不造成影响,Btrace脚本对其可以执行的动作做了很多限制
- 不能创建对象
- 不能抛出或者捕获异常
- 不能用synchronized关键字
- 不能对目标程序中的instace或者static变量
- 不能调用目标程序的instance或者static方法
- 脚本的field、method都必须是static的
- 脚本不能包括outer,inner,nested class
- 脚本中不能有循环,不能继承任何类,任何接口与assert语句
BTrace详细用法
1
|
btrace
[
-
I
<
include
-
path
>
]
[
-
p
<
port
>
]
[
-
cp
<
classpath
>
]
<
pid
>
<
btrace
-
script
>
[
<
args
>
]
|
- -I:没有这个表明跳过预编译
- include-path:指定用来编译脚本的头文件路径(关于预编译可参考例子ThreadBean.java)
- port:btrace agent端口,默认是2020
- classpath:编译所需类路径,一般是指btrace-client.jar等类所在路径
- pid:java进程id
- btrace-script:btrace脚本可以是.java文件,也可以是.class文件
- args:传递给btrace脚本的参数, 在脚本中可以通过$(), $length()来获取这些参数(定义在BTraceUtils中)
方法注解说明
- @OnMethod:指定使用当前注解的方法应该在什么情况下触发,claszz属性指定要匹配的类的全限定类名,可以用正则表达式:/类名的Pattern/匹配,用”+类名”匹配所有子类,用”@某某注解”匹配用该注解注解过的类method属性指定要匹配的方法名称,可以用正则表达式:/方法名称的Pattern/匹配type属性:void(java.lang.String)可以用于匹配:public void funcName(String param) throws Exception,location属性用@Location来表明,匹配了clazz,method情况,在方法执行的何时去执行脚本(前,后,异常,行,某个方法调用)
- @OnTimer:指定一个定时任务
- @OnExit:当脚本运行Sys.exit(code)时触发
- @OnError:当脚本运行抛出异常时触发
- @OnEvent:脚本运行时Ctrl+C可以发送事件
- @OnLowMemory:让你指定一个阀值,内存低于阀值触发
- @OnProbe:可以用一个xml文件来描述你想在什么时候触发该方法
方法参数注解说明
- @Self:目标对象本身
- @Retrun:目标程序方法返回值(Kind.RETURN)
- @ProbeClassName:目标类名
- @ProbeMethodName:目标方法名
- @targetInstance:@Location指定的clazz,method的目标(Kind.CALL)
- @targetMethodOrField:@Location指定的clazz,method的目标的方法或字段(Kind.CALL)
- @Duration:目标方法执行时间,单位是纳秒,需要与 Kind.RETURN 或者 Kind.ERROR 一起使用
这里我没有举太多例子,因为每人用BTrace的目的不一样,况且官方文档中已经有太多的例子说明,而使用方式已经在这里列出,所以就不再一一展开,后期我还总结下BTrace与jstack的用法,用来诊断OOM的问题.