Btrace1.3.9用户手册

本手册是基于版本1.3.9写的,若软件升级请参考项目(github)对应版本随包用户手册:${projectpath}/docs路径下的usersguide.html

概述

BTrace 中的B表示bytecode;它是一个可靠的,用来动态追踪Java应用程序的工具。工作方式是动态对运行中的Java程序进行字节码生成。BTrace会对运行中的Java程序的类插入一些追踪操作并与被追踪的目标程序进行交互。


BTrace植入过的代码,会一直在,直到应用重启为止。所以即使Btrace退出了,业务函数每次执行时都会执行Btrace植入的代码
BTrace植入过的代码,会一直在,直到应用重启为止。所以即使Btrace退出了,业务函数每次执行时都会执行Btrace植入的代码
BTrace植入过的代码,会一直在,直到应用重启为止。所以即使Btrace退出了,业务函数每次执行时都会执行Btrace植入的代码


Btrace术语

Probe Point(探测点)
追踪语句(或者一组追踪语句)被触发执行的“位置”或“事件”。也就是我们想要执行一些追踪语句的“位置”或“事件”。
Trace Actions or Actions(追踪执行)
probe被触发时,执行的追踪语句。
Action Methods(执行方法)
我的理解是定义追踪执行的方法,当然根据官方的说明这个方法应该是静态的。
在静态方法中定义probe触发所调用的trace语句,那么这种定义了trace脚本的静态方法就是"执行方法"
#BTrace程序结构
一个BTrace程序是其实就是一个普通的java类,特别之处就是由一个或者多个被(public static void)组合修饰的方法并且这些方法被BTrace对应的annotations注解。注解用来指出被追踪程序的位置(probe point)。追踪执行须书写在静态方法体中,也就是action方法(可以有多个action方法)。
#BTrace约束
为了保证追踪执行是“只读”的(也就是这些执行不可以修改被追踪程序的状态)和有限度的(比如在固定时间里结束)。一个BTrace程序只允许完成一些指定的执行。下面是BTrace一些不可以完成的事情:

  • 不能创建新的对象
  • 不能创建新的数组
  • 不能抛出异常
  • 不能捕获异常
  • 不能进行任何的实例函数或者静态函数 – 只有com.sun.btrace.BTraceUtils类中的静态函数或者BTrace程序自己声明的函数才可以被BTrace调用
  • 不可以在目标程序的类,或者对象的静态或者实例级别的field进行赋值。但是,BTrace自身的类是可以给它的静态field进行赋值的
  • 不能有outer,inner,嵌套的或者本地类。
  • 不能有同步代码块或者同步的函数
  • 不能有循环语句(for,while, do…while)
  • 不能继承其它类(父类只能是java.lang.Object)
  • 不能实现接口
  • 不能包含断言(assert)语句
  • 不能使用类字面值

这上面的种种限制可以通过一个配置改变:unsafe=true,在使用BTrace注解时修改该属性的默认值(false)为true,即@BTrace(unsafe=true);也可以启动选项中显式声明-Dcom.sun.btrace.unsafe=true(响应也有-u参数);现在你可以为所欲为了。BUT,这样做之前最好考虑好风险并再三检查脚本,请斟酌使用!

一个简单的程序

// import all BTrace annotations
import com.sun.btrace.annotations.*;
// import statics from BTraceUtils class
import static com.sun.btrace.BTraceUtils.*;
// @BTrace annotation tells that this is a BTrace program
@BTrace
public class HelloWorld {
    // @OnMethod annotation tells where to probe.
    // In this example, we are interested in entry 
    // into the Thread.start() method. 
    @OnMethod(
        clazz="java.lang.Thread",
        method="start"
    )
    public static void func() {
        // println is defined in BTraceUtils
        // you can only call the static methods of BTraceUtils
        println("about to start a thread!");
    }
}

以上的程序都可以对一个正在运行的Java进行追踪。这个程序会在目标程序调用Thread.start()函数来启动一个线程时打印出“about to start a thread!".还有其他一些有趣的探测点,比如,我们可以一个函数返回的时候插入一段探测执行,或者是一个函数碰到异常时也插入一段,在函数里用到的field,对象和数组的创建,代码行号等等。参考@OnMethod和其它注解来了解更多细节

运行BTrace的步骤

1、找到你要追踪的Java进程的ID。可以用JDK自带的jps程序找到你要的进程id。
2、编写一段BTrace程序 – 你也可以修改我们的样例程序
3、在命令行运行btrace工具:

btrace <pid> <btrace-script>

BTrace 命令行

btrace命令行工具运行命令如下:

btrace <options> <pid> <btrace source or .class file> <btrace arguments>
常用选项:
[-I <include-path>] [-p <port>] [-cp <classpath>]

参数说明:

where possible options include:
  --version             Show the version
  -v                    Run in verbose mode
  -o <file>             The path to store the probe output (will disable showing the output in console)
  -u                    Run in trusted mode
  -d <path>             Dump the instrumented classes to the specified path
  -pd <path>            The search path for the probe XML descriptors
  -classpath <path>     Specify where to find user class files and annotation processors
  -cp <path>            Specify where to find user class files and annotation processors
  -I <path>             Specify where to find include files
  -p <port>             Specify port to which the btrace agent listens for clients
  -statsd <host[:port]> Specify the statsd server, if any
  • include-path : 是一些用来查找头文件的目录。BTrace包含一个简单的预处理,支持# define,# include和条件编译。它不像一个完整的C / c++预处理器–而是一个有用的子集。详见demo代码“ThreadBean.java”,如果没有显式的声明选项-I,Btrace跳过预处理程序调用步骤。
  • port: BTrace代理程序所侦听的端口,这是可选的选项。默认是2020
  • classpath: 是一些用来查找jar文件的目录。默认是当前目录"."
  • pid:是要追踪目标程序id
  • btrace-script: 就是追踪程序本身。如果这是个java文件,那么提交前会进行编译。否则,它被认为已预编译(即它必须是一个类)并提交
  • arguments: 这是传递给BTrace程序的参数。BTrace程序可以通过内置的 符 号 来 引 用 这 些 参 数 , 符号来引用这些参数, length是这些参数的个数。

编译BTrace脚本

使用btracec脚本,我们可以对BTrace程序进行编译。btracec就是类似javac那样的程序,输入是一个BTrace程序,输出时一个.class文件。

btracec <options> <btrace source files>
常用选项:
[-I <include-path>] [-cp <classpath>] [-d <directory>]
where possible options include:
  -classpath <path> Specify where to find user class files and annotation processors
  -cp <path>        Specify where to find user class files and annotation processors
  -I <path>         Specify where to find include files
  -d <directory>    Specify where to place generated class files
  -trusted          Enable trusted script (eg. no checks)

参数函数见上一小节[参数说明]

使用BTrace代理来启动一个目标程序

now,我们已经知道如何追踪一个正在运行的Java程序。还可以通过BTrace代理来启动目标程序。若想追踪目标程序开始的时候作了什么事情,需要通过BTrace代理来启动它,并显式指定对应的追踪脚本。以下命令演示如何作。注意:这里制定的追踪脚本必须是已经编译好的(就是.class文件)。

java -javaagent:btrace-agent.jar=script=<pre-compiled-btrace-script1>[,<pre-compiled-btrace-script1>]* <MainClass> <AppArguments>

以这种方式启动的目标程序,追踪输出到当前目录下一个叫作< btrace-class-file-name>.btrace的文件中。如果你不想这个目标程序给其他的远程BTrace客户端使用,那么可以指定noServer=true这个参数给BTrace代理。
btracer的脚本专门做上面的事情的:

btracer <options> <compiled script> <java args>
常用选项:
<pre-compiled-btrace.class> <application-main-class>

支持的参数

Options:
    -v                    Run in verbose mode
    -u                    Run in unsafe mode
    -p <port>             BTrace agent server port
    -statsd <host[:port]> Use this StatsD server
    -o <file>             The path to a file the btrace agent will store its output
    -d <path>             Dump modified classes to the provided location
    -pd <path>            Search for the probe XML descriptors here
    --noserver            Don't start the socket server
    --stdout              Redirect the btrace output to stdout instead of writing it to an arbitrary file
    -bcp <cp>             Append to bootstrap class path
    -scp <cp>             Append to system class path
    -h                    This message

BTrace的注解

方法注解

  • @com.sun.btrace.annotations.OnMethod 该注解可用来指定目标类,目标方法,以及目标方法里的“位置”。加了该注解后的操作方法会在对应的方法运行到指定的“位置”时被执行。这该注解中,目标类用“clazz”属性来指定,而目标方法用“method”属性来指定。"clazz"可以是类的全路径(比如java.awt.Component或者用两个反斜杠中间的正则表达式,参考例子NewComponent.java和Classload.java来看它们的用法,正则表达式可以匹配0个或多个目标类,这个时候多个类都会被进行动态指令更换。如/java\.awt\.+/匹配java.awt包下的所有类)。方法名也可以用这样的正则表达式 来匹配零个或者多个多个方法。参考例子MultiClass.java来查看用法。 还有一种方法来指定追踪类和函数。被追踪的类和函数可以用注解来指定。比如,如果"clazz"属性是@javax.jws.Webservice.那么BTrace会会把所有注解是这个的函数都进行动态指令更换。类似地,方法级别的注解也可以用来执行方法。参看例子WebServiceTracker.java来了解如何使用。可以把正则表达式和注解放在一起用,比如@/com\.acme\…+/可以匹配任何类,只要这个类的注解能跟那段正则表达式匹配即可。可以通过指定父类来匹配多个类名,比如+java.lang.Runnable就可以匹配所有实现了java.lang.Runnable这个接口的类。参考例子SubtypeTracer.java来看它的用法。
  • @com.sun.btrace.annotations.OnTimer 该注解可以用来执行那些需要周期性(间隔是毫秒)的追踪操作。参考Histogram.java来看它的用法。
  • @com.sun.btrace.annotations.OnError 该注解可以用来指定当任何异常抛出时需要执行的操作。被该注解修饰后的BTrace函数会在同一个BTrace类的其他操作方法抛出异常时执行。
  • **@com.sun.btrace.annotations.OnExit 该注解用来执行党BTrace代码调用了exit(int)结束追踪会话后需要执行的操作。参考例子ProbeExit.java来了解如何使用。
  • @com.sun.btrace.annotations.OnEvent 该注解用来追踪函数与"外部”的事件关联起来。当BTrace客户端发送了一个“事件”后,该注解里的操作就会被执行。客户端发送的事件可能是由用户触发的(比如按下Ctrl-C)。事件的名字是个字符串,这样追踪操作就只会在对应的事件触发后被执行。到目标为止,BTrace命令行客户端会在用户按下Ctrl-C后发送事件,参考例子HistoOnEvent.java来了解用法。
  • @com.sun.btrace.annotations.OnLowMemory 该注解可以用来追踪特定内存阈值被用光的事件。参看例子MemAlerter.java了解用法。
  • @com.sun.btrace.annotations.OnProbe 该注解可以用来避免使用BTrace脚本的内部类。@OnProbe探测点被映射到一个或多个@OnMethod上。目前这个映射是通过一个XML探测描述文件类指定的(这个文件会被BTrace代理所使用)。参考例子SocketTracker1.java和对应的描述文件java.net.socket.xml.当运行这个例子时,xml文件需要放在目标JVM所有运行的目录下(或者修改btracer.bat中的probeDescPath选项来指向任意的xml文件)。
  • @com.sun.btrace.annotations.Location:该注解在一个traced/probed方法中指定一个特定的“位置”
  • @com.sun.btrace.annotations.Simpled:标记@OnMethod注解处理器采样。采样处理程序时并不是所有的事件将被追踪,只有一个统计样品与给定的意思。在默认情况下使用一种自适应采样。BTrace将增加或减少样品之间的调用数量保持平均时间窗口,因此减少整体的开销。

参数相关的注解

  • @com.sun.btrace.annotations.Self:该注解把一个参数标识为保留了目标函数所指向的this的值。参考例子AWTEventTracer.java和AllCalls1.java.
  • @com.sun.btrace.annotations.Return:该注解说明这个参数保存目标函数的返回值。参考例子Classload.java
  • @com.sun.btrace.annotations.ProbeClassName:所修饰的参数保留了探测类的类名 。参看AllMethods.java(有多个探测类)
  • @com.sun.btrace.annotations.ProbeMethodName:所修饰的参数保留了探测函数的函数名。参考WebServiceTracker.java(多个探测函数)
  • @com.sun.btrace.annotations.TargetInstance:修饰的参数保留了被调用的实例。参考例子AllCall2.java.
  • @com.sun.btrace.annotations.TargetMethodOrField:该注解修饰的参数保存了调用的函数名。参考AllCalls1.java 和AllCall2.java
  • @com.sun.btrace.annotations.Duration:探测方法参数标记为持续时间值的接收者,即目标方法执行的时间,单位纳秒。只是用带Location属性的@OnMethod,并且需要配合Kind.ERROR或者Kind.RETURN使用

##无注解的参数

没有注解的BTrace探测函数参数是用来作签名匹配的,因为他们必须必须在固定的位置上出现。然而,它们可以和其他的注解的参数进行交换。如果一个参数的类型是AnyType[],它就会“吃”掉所所有剩下的参数。没有注解的参数的具体含义与他们所在的位置有关:

名称作用
Kind.ARRAY_GET数组元素加载
Kind.ARRAY_SET数组元素存储
Kind.CALL方法调用
Kind.CATCH异常捕获
Kind.CHECKCASTcheckcast
Kind.ENTRY方法进入。意指进入匹配probe点,跟你@Location设置的clazz和method没有任何关系
Kind.ERROR错误,异常没有捕获,返回
Kind.FIELD_GETfield获取
Kind.FIELD_SETfield设置
Kind.INSTANCEOF实例检测
Kind.LINE源代码行号
Kind.NEW创建新实例
Kind.NEWARRAY新的数组对象被创建
Kind.RETURN意指从某个匹配probe的方法中调用了匹配A class method的点,一定要和clazz,method配合使用。clazz和method的默认值为"",所以不能被匹配
Kind.SYNC_ENTRY进入一个同步方法锁
Kind.SYNC_EXIT离开一个同步方法锁
Kind.THROW抛出异常

字段相关的注解

  • @com.sun.btrace.annotations.Export BTrace字段使用该注解来说明它已经被映射到一个jvmstat计数器上。使用该注解,BTrace程序可以把追踪计数器暴露给外部的jvmstat客户端(比如jstat)。参考例子ThreadCounter.java
  • @com.sun.btrace.annotations.Property该注解可以把一个字段标识为一个MBean属性。如果一个BTrace类至少有一个静态的字段使用了该注解。那么一个MBean就会被创建并且注册到平台MBean服务器上。JMX客户端比如VisualVM,jconsole可以访问这个字段来查看BTrace的MBean。在把BTrace附加到目标程序上后,你可以把VisualVM或者jconsole也附加到同一个目标程序上来查看刚创建好的MBean属性。通过VisualVM或者jconsole,你可以通过MBeans tab页来查看BTrace相关的域,然后查看它们的值。参考例子ThreadCounterBean.java 和HistogramBean.java来了解用法
  • @com.sun.btrace.annotations.TLS BTrace字段使用该注解来说明它自己是一个线程本地字段(thread local field).注意你只能在@OnMethod注解后的函数里访问这样的字段。每个Java线程都有一个这个字段的拷贝。为了让这样的方式能够工作,这个字段的类型只能是immutable(比如原始类型) 或者是cloneable (实现了Cloneable接口并且覆盖了clone()函数)的。这些线程本地字段可以被BTrace程序用来识别它是否在同一个线程里执行了多个探测操作。参考例子OnThrow.java和WebServiceTracker.java

类相关的注解

  • @com.sun.btrace.annotations.DTrace该注解用来把一小段D脚本(嵌在BTrace 的java类中)和BTrace程序关联起来。参考例子DTraceInline.java
  • @com.sun.btrace.annotations.DTraceRef 和上个注解一样,不同的是D脚本是在独立的文件中,不是嵌在java类中。
  • @com.sun.btrace.annotations.BTrace必须使用该注解来指定一个Java类是BTrace程序。BTrace编译器会强制查找该注解,BTrace代理也会检查这个是否有该注解。如果没有,则提示错误,并且不会执行。

#DTrace集成
Solaris DTrace是一款动态的、安全的,针对Solaris程序的追踪系统–包括内核和用户程序。因为b/w DTrace和BTrace明显的相似之处,很自然的期待集成b/w BTrace和DTrace。有两种方法,使BTrace和DTrace BTrace集成。

  • BTrace程序可以提高DTrace探测,通过调用dtraceProbe——看到BTraceUtils javadoc上面提到。对于这个功能,您需要运行在Solaris 10或超越。为其他平台(Solaris 9或低于或任何其他操作系统),dtraceProbe()将是一个空操作。
  • BTrace程序可以与它关联d脚本,由@DTrace注释(如果d脚本是一个简单的一个班轮)或@DTraceRef如果d脚本的时间更长,因此存储BTrace之外的项目。见下面的DTrace集成在BTrace样品部分样品。该特性使用DTrace Java API。对于这个工作(o.e DTrace特性。,能够运行相关的d脚本),您需要运行在Solaris 11构建35或超越。您可能需要检查一下你是否已经/usr/share/lib/java/dtrace.jar在您的机器上。@DTrace和@DTraceRef注释忽略其他平台上的Solaris 10(或低于或任何其他操作系统)。


补上示例…
btrace用户手册1.3.9
btrace注解
btrace示例

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.btrace扩展是在btrace已由功能上进行的扩展,原有功能和使用方式依然没变。目前版本扩展了两个功能:接口时间监控和接口时间调用树监控。扩展之后的btrace功能使用时都不需要写btrace脚本。 2.使用接口时间监控功能,命令格式为btrace -E mCall pid clazz method,其中clazz 为需要监控的方法所在的类,method为需要监控的方法名称。例如btrace -E mCall 5100 cn.com.icegarden.test.BtraceMain spendTime 3.使用接口时间调用树功能,命令为btrace -E mCallTree clazz method innerClazzes innerMethods 其中clazz为要监控的入口方法所在的类,method为要监控的入口方法名称。 innerClazzes和innerMethods为要监控的入口方法内部调用的方法和所在的类。举例来讲:cn.icegarden.com.A类的a方法中调用了cn.icegarden.com.B类的b方法、cn.icegarden.com.C类的c方法。cn.icegarden.com.C类的c方 法中又调用了cn.icegarden.com.D的d方法。如果要监控A类的a方法在调用这些方法上的时间,使用btrace扩展的调用树功能可以使用命令: btrace -E mCallTree 4432 cn.icegarden.com.A a cn.icegarden.com.B,cn.icegarden.com.C,cn.icegarden.com.D b,c,d 输出结果如下: 0 [9,999ms (1,000ms), 100%] - a +---0 [1,999ms, 20%, 20%] - b `---1,999 [7,000ms (3,000ms), 70%, 70%] - c `---1,999 [4,000ms, 57%, 40%] - d 每一个节点都会输出如下格式的内容: a [b ms,c%,d%] - e 其中a 是打点开始到当前节点开始执行期间的时间间隔毫秒值。 b 是当前节点的方法总共执行的时间。 c 是当前节点执行时间占上一个节点总执行时间的百分比。 d 是当前节点执行时间占入口节点总执行时间的百分比。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值