btrace是sun推出的一款java性能监控工具,利用java agent 和 jvm attach技术,可以不停机的情况下监控线上情况,并且做到最少的侵入,占用最少的系统资源。
详细见官方文档
另外btrace有很严格的限制,比如拼接字符串、循环、递归、以及我们平时经常用的一些方法都不可以用,他有他自己专门的类库。
btrace还提供了VisualVM Plugin 以及Netbeans Plugin。
具体使用如下。
1.下载btrace包 http://kenai.com/projects/btrace/downloads/directory/releases。
2.设置环境变量。
3.定制自己需要的脚本。
4.jps命令查出需要监控的jvm pid。
5.调用命令 btrace <pid> <自己定制的脚本> <输出文件> eg:btrace 3045 PrintExecuteTime.java > time.log
我经常使用的功能一是监控某些方法的耗时,二是查看某些方法的参数值,三是监控内存使用情况。
脚本举例如下
1.监控方法参数(数组)
- import static com.sun.btrace.BTraceUtils.print;
- import static com.sun.btrace.BTraceUtils.printArray;
- import static com.sun.btrace.BTraceUtils.println;
- import static com.sun.btrace.BTraceUtils.probeClass;
- import static com.sun.btrace.BTraceUtils.probeMethod;
- import com.sun.btrace.annotations.BTrace;
- import com.sun.btrace.annotations.OnMethod;
- @BTrace
- public class PrintArgArray {
- /**
- * 此方法打印出Test类中的mergeArray(Long[] arrayOne, Long[] arrayTwo)方法传入的参数
- * 参数名字一定要和监控对象的方法参数名字一致
- *
- * @param arrayOne 监控参数一
- * @param arrayTwo 监控参数二
- * @author jerry
- */
- @OnMethod(clazz = "com.jerry.test.Test", method = "mergeArray")
- // 此处写明要监控的包、类、方法等 可以使用正则匹配
- public static void anyRead(Long[] arrayOne, Long[] arrayTwo) {
- // 打印监控的类名
- print(probeClass());
- print(" [");
- // 打印监控的方法名
- print(probeMethod());
- println("]");
- if (arrayOne != null) {
- printArray(arrayOne);
- } else {
- println("the arguments is null!");
- }
- if (arrayTwo != null) {
- printArray(arrayTwo);
- } else {
- println("the arguments is null!");
- }
- }
- }
import static com.sun.btrace.BTraceUtils.print;
import static com.sun.btrace.BTraceUtils.printArray;
import static com.sun.btrace.BTraceUtils.println;
import static com.sun.btrace.BTraceUtils.probeClass;
import static com.sun.btrace.BTraceUtils.probeMethod;
import com.sun.btrace.annotations.BTrace;
import com.sun.btrace.annotations.OnMethod;
@BTrace
public class PrintArgArray {
/**
* 此方法打印出Test类中的mergeArray(Long[] arrayOne, Long[] arrayTwo)方法传入的参数
* 参数名字一定要和监控对象的方法参数名字一致
*
* @param arrayOne 监控参数一
* @param arrayTwo 监控参数二
* @author jerry
*/
@OnMethod(clazz = "com.jerry.test.Test", method = "mergeArray")
// 此处写明要监控的包、类、方法等 可以使用正则匹配
public static void anyRead(Long[] arrayOne, Long[] arrayTwo) {
// 打印监控的类名
print(probeClass());
print(" [");
// 打印监控的方法名
print(probeMethod());
println("]");
if (arrayOne != null) {
printArray(arrayOne);
} else {
println("the arguments is null!");
}
if (arrayTwo != null) {
printArray(arrayTwo);
} else {
println("the arguments is null!");
}
}
}
2.监控使用时间
- import static com.sun.btrace.BTraceUtils.name;
- import static com.sun.btrace.BTraceUtils.print;
- import static com.sun.btrace.BTraceUtils.println;
- import static com.sun.btrace.BTraceUtils.probeClass;
- import static com.sun.btrace.BTraceUtils.probeMethod;
- import static com.sun.btrace.BTraceUtils.str;
- import static com.sun.btrace.BTraceUtils.strcat;
- import static com.sun.btrace.BTraceUtils.timeMillis;
- import com.sun.btrace.annotations.BTrace;
- import com.sun.btrace.annotations.Kind;
- import com.sun.btrace.annotations.Location;
- import com.sun.btrace.annotations.OnMethod;
- import com.sun.btrace.annotations.TLS;
- /**
- * 监控方法耗时
- *
- * @author jerry
- */
- @BTrace
- public class PrintTimes {
- /**
- * 开始时间
- */
- @TLS
- private static long startTime = 0;
- /**
- * 方法开始时调用
- */
- @OnMethod(clazz = "/com//.jerry//../", method = "/.+/")
- public static void startMethod() {
- startTime = timeMillis();
- }
- /**
- * 方法结束时调用<br>
- * Kind.RETURN这个注解很重要
- */
- @SuppressWarnings("deprecation")
- @OnMethod(clazz = "/com//.jerry//../", method = "/.+/", location = @Location(Kind.RETURN))
- public static void endMethod() {
- print(strcat(strcat(name(probeClass()), "."), probeMethod()));
- print(" [");
- print(strcat("Time taken : ", str(timeMillis() - startTime)));
- println("]");
- }
- }
import static com.sun.btrace.BTraceUtils.name;
import static com.sun.btrace.BTraceUtils.print;
import static com.sun.btrace.BTraceUtils.println;
import static com.sun.btrace.BTraceUtils.probeClass;
import static com.sun.btrace.BTraceUtils.probeMethod;
import static com.sun.btrace.BTraceUtils.str;
import static com.sun.btrace.BTraceUtils.strcat;
import static com.sun.btrace.BTraceUtils.timeMillis;
import com.sun.btrace.annotations.BTrace;
import com.sun.btrace.annotations.Kind;
import com.sun.btrace.annotations.Location;
import com.sun.btrace.annotations.OnMethod;
import com.sun.btrace.annotations.TLS;
/**
* 监控方法耗时
*
* @author jerry
*/
@BTrace
public class PrintTimes {
/**
* 开始时间
*/
@TLS
private static long startTime = 0;
/**
* 方法开始时调用
*/
@OnMethod(clazz = "/com//.jerry//../", method = "/.+/")
public static void startMethod() {
startTime = timeMillis();
}
/**
* 方法结束时调用<br>
* Kind.RETURN这个注解很重要
*/
@SuppressWarnings("deprecation")
@OnMethod(clazz = "/com//.jerry//../", method = "/.+/", location = @Location(Kind.RETURN))
public static void endMethod() {
print(strcat(strcat(name(probeClass()), "."), probeMethod()));
print(" [");
print(strcat("Time taken : ", str(timeMillis() - startTime)));
println("]");
}
}
3.监控内存
- import static com.sun.btrace.BTraceUtils.*;
- import java.lang.management.MemoryUsage;
- import com.sun.btrace.annotations.BTrace;
- import com.sun.btrace.annotations.OnLowMemory;
- /**
- * 监控内存使用
- *
- * @author jerry
- */
- @BTrace
- public class PrintMemory {
- /*
- * 指定内存区域低于一定的界限的时候才内存使用打印数据<br> 也可以指定时间间隔打印内存使用
- */
- @OnLowMemory(pool = "Tenured Gen", threshold = 6000000)
- public static void printMem(MemoryUsage mu) {
- print("MemoryUsage : ");
- println(mu);
- print("FreeMem : ");
- println(freeMemory());
- print("Heap:");
- println(heapUsage());
- print("Non-Heap:");
- println(nonHeapUsage());
- }
- }