Basic Installation
Download the latest btrace in the release on github btrace project
https://github.com/btraceio/btrace/releases
After decompression, adding btrace bin directory into the environment variable
Instructions btrace <options> <PID> <btrace脚本>
visualvm installation btrace
First, install the plug-in visualvm btrace in
the menu bar> Tools> Plugins> Available Plugins> btrace
After installation is complete, as follows
A simple example
package me.cayun.javalab;
public class {
private static Tmp output(String s, int x) { for (int i = 0; i < 10000; i++) { System.out.println(s + " " + x); }
Tmp t = new Tmp(); t.setS(s); t.setX(x); return t; }
public static void main(String[] args) throws InterruptedException { while (true) { output("hello", 30); Thread.sleep(2000); } } }
class Tmp { private String s; private int x;
public String getS() { return s; }
public void setS(String s) { this.s = s; }
public int getX() { return x; }
public void setX(int x) { this.x = x; } }
|
目标
- 输出该函数的参数
- 输出该函数的执行时间
- 输出该函数的返回值
btrace脚本
import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.*;
import com.sun.btrace.AnyType; import java.lang.reflect.Field;
public class TracingScript {
@OnMethod(clazz="me.cayun.javalab.BtraceMain", method="output", location=@Location(Kind.RETURN)) public static void output(String s, int b, @Return AnyType result, @Duration long runningTime) { println(strcat("arg1: ", s)); println(strcat("arg2: ", str(b))); Class<?> clazz = classOf(result); println(strcat("return: ", str(get(field(clazz, "s"), result)))); println(strcat("time: ", str(runningTime / 1000000))); } }
|
解释
- @BTrace 表明这是一个btrace脚本
- @OnMethod 指定方法入口,其中clazz和method参数可以使用正则表达式
- @Location 表示拦截的时机,
- Kind.ENTRY表示在进入方法时执行,默认为ENTRY
- Kind.RETURN表示方法执行后执行
- @Return 表示返回参数,前提location为Kind.RETURN
- @Duration 表示函数执行时间,单位: 纳秒,前提location为Kind.RETURN
- 获取类的某个属性值, get(field(clazz, name), object);
另一种获取函数运行时间的方法
还是刚刚那段Java代码,新的btrace脚本如下
import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.*;
public class TracingScript {
@TLS private static long startTime; @OnMethod(clazz="me.cayun.javalab.BtraceMain", method="output") public static void onCall() { startTime = timeMillis(); }
@OnMethod(clazz="me.cayun.javalab.BtraceMain", method="output", location=@Location(Kind.RETURN)) public static void onReturn() { println(str(timeMillis() - startTime)); } }
|
解释
- @TLS 用来将一个脚本变量与一个ThreadLocal变量关联
btrace直接使用项目中的类
public class {
public static AtomicInteger i = new AtomicInteger();
private static void inc(int x) { i.addAndGet(x); }
public static void main(String[] args) throws InterruptedException { while (大专栏 btrace简单使用eyword">true) { inc(new Random().nextInt(10)); System.out.println(i.get()); Thread.sleep(2000); } } }
|
在第一个示例中,调用项目中的类使用的是反射的方式,但其实btrace也可以直接使用项目的类
目标
- 获取BtraceMain中的i的值
btrace脚本
import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.*;
import me.cayun.javalab.BtraceMain;
public class TracingScript {
@OnMethod(clazz="me.cayun.javalab.BtraceMain", method="inc") public static void onCall(@Self BtraceMain bt) { println(str(bt.i)); } }
|
emm~,只需要在前面import相应的类即可
如果变量为私有变量,仍然需要通过反射的方式获取
btrace关于map的操作
以下代码摘自btrace源码中com.sun.btrace.BTraceUtils函数
public static void printMap(Map map) { BTraceRuntime.printMap(map); }
public static <K, V> Map<K, V> newHashMap() { return Collections.newHashMap(); }
public static <K, V> Map<K, V> newWeakMap() { return Collections.newWeakMap(); }
public static <K, V> V get(Map<K, V> map, K key) { return Collections.get(map, key); }
public static <K, V> boolean containsKey(Map<K, V> map, K key) { return Collections.containsKey(map, key); }
public static <K, V> boolean containsValue(Map<K, V> map, V value) { return Collections.containsValue(map, value); }
public static <K, V> V put(Map<K, V> map, K key, V value) { return Collections.put(map, key, value); }
public static <K, V> V remove(Map<K, V> map, K key) { return Collections.remove(map, key); }
public static <K, V> void clear(Map<K, V> map) { Collections.clear(map); }
public static <K, V> int size(Map<K, V> map) { return Collections.size(map); }
public static <K, V> boolean isEmpty(Map<K, V> map) { return Collections.isEmpty(map); }
|
其他常见用法
打印调用栈
package me.cayun.javalab;
public class {
private static void gc1() { gc2(); }
private static void gc2() { gc3(); }
private static void gc3() { System.gc(); }
public static void main(String[] args) throws InterruptedException { while (true) { gc1(); Thread.sleep(10000); } } }
|
btrace脚本
import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.*;
public class TracingScript {
@OnMethod(clazz="java.lang.System", method="gc") public static void onCallGC() { jstack(); } }
|
查看VM/内存/CPU等信息
可以参考BTraceUtils的源码
https://github.com/btraceio/btrace/blob/master/src/share/classes/com/sun/btrace/BTraceUtils.java
参考
[1] btrace github
[2] BTrace 简明使用手册
[3] BTrace使用