小试牛刀之BTrace

来源:互联网 发布:编程数学要求高吗 编辑:程序博客网 时间:2024/04/30 18:11

BTrace is a safe, dynamic tracing tool for the Java platform. BTrace can be used to dynamically trace a running Java program (similar to DTrace for OpenSolaris applications and OS). BTrace dynamically instruments the classes of the target application to inject tracing code ("bytecode tracing").

上面是BTrace官网对于BTrace的介绍。我们可以用BTrace来探测系统运行时的状况。下面就小试牛刀,写个例子跑跑看。

下面是一个用来探测哪些方法的执行时间超过某个阈值的探针。如果超过阈值,会记录该次调用的调用栈,

import static com.sun.btrace.BTraceUtils.*;import com.sun.btrace.annotations.*;@BTracepublic class Tracker {    @OnMethod(            clazz = "/me\\.kisimple\\.just4fun\\..*/",            method = "/.*/",            location = @Location(Kind.RETURN)    )    public static void trace(@ProbeClassName String pcn,                             @ProbeMethodName String pmn,                             @Duration long duration) {        // duration的单位是纳秒        if(duration > 3000000000l) {            print(Strings.strcat("#Duration of ",                            Strings.strcat(Strings.strcat(pcn, "."), pmn)));            print(" is ");            print(duration);            println("#");            jstack();        }    }}

BTrace支持正则表达式,a regular expression specified within two forward slashes,也就是"/<regexp>/"这样子的。我们的例子是探测me.kisimple.just4fun包下的任何类的任何方法。

模拟一个被探测对象,

public class Main {    public static void main(String[] args) throws Exception{        while(true) {            bar();            foo();        }    }    private static void bar() throws InterruptedException {        Thread.sleep(5000);    }    private static void foo() throws InterruptedException {        Thread.sleep(1000);    }}

运行之前需要设置环境变量,看下bin目录下的btrace脚本就知道了,

#! /bin/shif [ -z "$BTRACE_HOME" -o ! -d "$BTRACE_HOME" ] ; then  # resolve links - $0 could be a link to btrace's home  PRG="$0"  progname=`basename "$0"`  BTRACE_HOME=`dirname "$PRG"`/..  BTRACE_HOME=`cd "$BTRACE_HOME" && pwd`fiif [ -f "${BTRACE_HOME}/build/btrace-client.jar" ] ; then    if [ "${JAVA_HOME}" != "" ]; then       case "`uname`" in          Darwin*)              # In Mac OS X, tools.jar is classes.jar and is kept in a               # different location. Check if we can locate classes.jar              # based on ${JAVA_VERSION}              TOOLS_JAR="/System/Library/Frameworks/JavaVM.framework/Versions/${JAVA_VERSION}/Classes/classes.jar"              # if we can't find, try relative path from ${JAVA_HOME}. Usually,              # /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home              # is JAVA_HOME. (or whatever version beyond 1.6.0!)              if [ ! -f ${TOOLS_JAR} ] ; then                  TOOLS_JAR="${JAVA_HOME}/../Classes/classes.jar"               fi              # If we still can't find, tell the user to set JAVA_VERSION.              # This way, we can avoid zip file errors from the agent side              # and "connection refused" message from client.              if [ ! -f ${TOOLS_JAR} ] ; then                  echo "Please set JAVA_VERSION to the target java version"                  exit 1              fi          ;;          *)              TOOLS_JAR="${JAVA_HOME}/lib/tools.jar"          ;;       esac       ${JAVA_HOME}/bin/java -Dcom.sun.btrace.probeDescPath=. -Dcom.sun.btrace.dumpClasses=false -Dcom.sun.btrace.debug=false -Dcom.sun.btrace.unsafe=false -cp ${BTRACE_HOME}/build/btrace-client.jar:${TOOLS_JAR}:/usr/share/lib/java/dtrace.jar com.sun.btrace.client.Main $*    else       echo "Please set JAVA_HOME before running this script"       exit 1    fielse    echo "Please set BTRACE_HOME before running this script"    exit 1fi

OK,设置环境变量,

export BTRACE_HOME=/home/blues/btraceexport PATH=$PATH:$BTRACE_HOME/bin

执行btrace命令,

$ btrace 6860 Projects/just4fun/src/me/kisimple/just4fun/Tracker.java #Duration of me.kisimple.just4fun.Main.bar is 5000179210#me.kisimple.just4fun.Main.bar(Main.java:17)me.kisimple.just4fun.Main.main(Main.java:10)sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)java.lang.reflect.Method.invoke(Method.java:606)com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)#Duration of me.kisimple.just4fun.Main.bar is 5000131459#me.kisimple.just4fun.Main.bar(Main.java:17)me.kisimple.just4fun.Main.main(Main.java:10)sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)java.lang.reflect.Method.invoke(Method.java:606)com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

Alright, have fun ^_^

参考资料

  • https://kenai.com/projects/btrace/pages/UserGuide
  • http://bluedavy.me/?p=185
0 0
原创粉丝点击