btrace simple to use

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;
}
}

目标

  1. 输出该函数的参数
  2. 输出该函数的执行时间
  3. 输出该函数的返回值

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 {
/* put your code here */

@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 {
/* put your code here */

@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也可以直接使用项目的类

目标

  1. 获取BtraceMain中的i的值

btrace脚本


import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;

import me.cayun.javalab.BtraceMain;


public class TracingScript {
/* put your code here */

@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 {
/* put your code here */

@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使用

Guess you like

Origin www.cnblogs.com/lijianming180/p/12032682.html