实时监控运行中java程序工具:btrace
2014-05-13 22:06
405 查看
文章主要部分摘自:/article/3940863.html
一、背景
在生产环境中可能经常遇到各种问题,定位问题需要获取程序运行时的数据信息,如方法参数、返回值、全局变量、堆栈信息等。为了获取这些数据信息,我们可以通过改写代码,增加日志信息的打印,再发布到生产环境。通过这种方式,一方面将增大定位问题的成本和周期,对于紧急问题无法做到及时响应;另一方面重新部署后环境可能已被破坏,很难重新问题的场景。
二、BTrace功能
BTrace天生就为解决这类问题而来,它可以动态地跟踪java运行程序。通过hotswap技术,动态将跟踪字节码注入到运行类中,对运行代码侵入较小,对性能上的影响可以忽略不计。
BTrace在使用上有很多限制条件,如不能创建对象、数组、抛出和捕获异常、循环等,具体限制条件参考用户文档中的BTrace Restrictions。用户文档地址: http://kenai.com/projects/btrace/pages/UserGuide。
根据官方声明,不当地使用btrace可能导致jvm崩溃,如BTrace使用错误的.class文件,Hotspot JVM自身存在的hotswap bug等。可以先在本地验证BTrace脚本的正确性,再传到生产环境中定位问题。
三、安装步骤
1. 下载安装压缩包,最新版本的是1.2.4
下载页面:https://kenai.com/projects/btrace/downloads/directory/releases
Linux版本1.2.4:https://kenai.com/projects/btrace/downloads/download/releases/release-1.2.4/btrace-bin.tar.gz
windows版本1.2.4:https://kenai.com/projects/btrace/downloads/download/releases/release-1.2.4/btrace-bin.zip
2. 解压缩,命令脚本在bin目录中。
3. 设置JAVA_HOME环境变量
4.可以将bin目录放到环境变量PATH中去,方便执行用。
5. 对于linux环境,需要对脚本增加可执行权限。
四、使用方法
BTrace主要包含btracec和btrace两个命令编译和启动BTrace脚本:
1. btrace
功能: 用于运行BTrace跟踪程序。
命令格式:
btrace [-I <include-path>] [-p <port>] [-cp <classpath>] <pid> <btrace-script> [<args>]
示例:
btrace -cp build/ 1200 AllCalls1.java
参数含义:
include-path指定头文件的路径,用于脚本预处理功能,可选;
port指定BTrace agent的服务端监听端口号,用来监听clients,默认为2020,可选;
classpath用来指定类加载路径,默认为当前路径,可选;
pid表示进程号,可通过jps命令获取;
btrace-script即为BTrace脚本;btrace脚本如果以.java结尾,会先编译再提交执行。可使用btracec命令对脚本进行预编译。
args是BTrace脚本可选参数,在脚本中可通过"$"和"$length"获取参数信息。
2. jvisualvm插件
BTrace提供了jvisualvm插件,强烈推荐在jvisualvm中编写和测试BTrace脚本,启动、关闭、发送事件、增加classpath都非常方便。
五、BTrace实战
1. 示例代码
示例代码定义了Counter计数器,有一个add()方法,每次增加随机值,总数保存在totalCount属性中。
Btracetest.java代码
package com.learnworld;
import java.util.Random;
public class BTraceTest {
public static void main(String[] args) throws Exception {
Random random = new Random();
// 计数器
Counter counter = new Counter();
while (true) {
// 每次增加随机值
counter.add(random.nextInt(10));
Thread.sleep(1000);
}
}
}
Counter.java代码
package com.learnworld;
public class Counter {
// 总数
private static int totalCount = 0;
public int add(int num) throws Exception {
totalCount += num;
sleep();
return totalCount;
}
public void sleep() throws Exception {
Thread.sleep(1000);
}
}
2. 常见使用场景
下面通过几个常见使用场景演示如何使用BTrace脚本。
1) 获取add()方法参数值和返回值。
Java代码
import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.*; @BTrace public class TracingScript { @OnMethod( clazz="com.learnworld.Counter", method="add", location=@Location(Kind.RETURN) ) public static void traceExecute(int num,@Return int result){ println("====== "); println(strcat("parameter num: ",str(num))); println(strcat("return value:",str(result))); } }
2) 定时获取Counter类的属性值totalCount。
Java代码
import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.*; @BTrace public class TracingScript { private static Object totalCount = 0; @OnMethod( clazz="com.learnworld.Counter", method="add", location=@Location(Kind.RETURN) ) public static void traceExecute(@Self com.learnworld.Counter counter){ totalCount = get(field("com.learnworld.Counter","totalCount"), counter); } @OnTimer(1000) public static void print(){ println("====== "); println(strcat("totalCount: ",str(totalCount))); } }
3) 获取add方法执行时间。
Java代码
import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.*; @BTrace public class TracingScript { @TLS private static long startTime = 0; @OnMethod( clazz="com.learnworld.Counter", method="add" ) public static void startExecute(){ startTime = timeNanos(); } @OnMethod( clazz="com.learnworld.Counter", method="add", location=@Location(Kind.RETURN) ) public static void endExecute(@Duration long duration){ long time = timeNanos() - startTime; println(strcat("execute time(nanos): ", str(time))); println(strcat("duration(nanos): ", str(duration))); } }
4) 获取add()方法调用方法sleep()次数。
Java代码
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;
@BTrace
public class TracingScript {
private static long count;
@OnMethod(
clazz="/.*/",
method="add",
location=@Location(value=Kind.CALL, clazz="/.*/", method="sleep")
)
public static void traceExecute(@ProbeClassName String pcm, @ProbeMethodName String pmn,
@TargetInstance Object instance, @TargetMethodOrField String method){
println("====== ");
println(strcat("ProbeClassName: ",pcm));
println(strcat("ProbeMethodName: ",pmn));
println(strcat("TargetInstance: ",str(classOf(instance))));
println(strcat("TargetMethodOrField : ",str(method)));
count++;
}
@OnEvent
public static void getCount(){
println(strcat("count: ", str(count)));
}
}
参考资料:
/article/3940863.html
http://www.linuxidc.com/Linux/2012-12/76155.htm
/article/5888880.html
/article/7606767.html
/article/3783623.html
/content/2744804.html
一、背景
在生产环境中可能经常遇到各种问题,定位问题需要获取程序运行时的数据信息,如方法参数、返回值、全局变量、堆栈信息等。为了获取这些数据信息,我们可以通过改写代码,增加日志信息的打印,再发布到生产环境。通过这种方式,一方面将增大定位问题的成本和周期,对于紧急问题无法做到及时响应;另一方面重新部署后环境可能已被破坏,很难重新问题的场景。
二、BTrace功能
BTrace天生就为解决这类问题而来,它可以动态地跟踪java运行程序。通过hotswap技术,动态将跟踪字节码注入到运行类中,对运行代码侵入较小,对性能上的影响可以忽略不计。
BTrace在使用上有很多限制条件,如不能创建对象、数组、抛出和捕获异常、循环等,具体限制条件参考用户文档中的BTrace Restrictions。用户文档地址: http://kenai.com/projects/btrace/pages/UserGuide。
根据官方声明,不当地使用btrace可能导致jvm崩溃,如BTrace使用错误的.class文件,Hotspot JVM自身存在的hotswap bug等。可以先在本地验证BTrace脚本的正确性,再传到生产环境中定位问题。
三、安装步骤
1. 下载安装压缩包,最新版本的是1.2.4
下载页面:https://kenai.com/projects/btrace/downloads/directory/releases
Linux版本1.2.4:https://kenai.com/projects/btrace/downloads/download/releases/release-1.2.4/btrace-bin.tar.gz
windows版本1.2.4:https://kenai.com/projects/btrace/downloads/download/releases/release-1.2.4/btrace-bin.zip
2. 解压缩,命令脚本在bin目录中。
3. 设置JAVA_HOME环境变量
4.可以将bin目录放到环境变量PATH中去,方便执行用。
5. 对于linux环境,需要对脚本增加可执行权限。
四、使用方法
BTrace主要包含btracec和btrace两个命令编译和启动BTrace脚本:
1. btrace
功能: 用于运行BTrace跟踪程序。
命令格式:
btrace [-I <include-path>] [-p <port>] [-cp <classpath>] <pid> <btrace-script> [<args>]
示例:
btrace -cp build/ 1200 AllCalls1.java
参数含义:
include-path指定头文件的路径,用于脚本预处理功能,可选;
port指定BTrace agent的服务端监听端口号,用来监听clients,默认为2020,可选;
classpath用来指定类加载路径,默认为当前路径,可选;
pid表示进程号,可通过jps命令获取;
btrace-script即为BTrace脚本;btrace脚本如果以.java结尾,会先编译再提交执行。可使用btracec命令对脚本进行预编译。
args是BTrace脚本可选参数,在脚本中可通过"$"和"$length"获取参数信息。
2. jvisualvm插件
BTrace提供了jvisualvm插件,强烈推荐在jvisualvm中编写和测试BTrace脚本,启动、关闭、发送事件、增加classpath都非常方便。
五、BTrace实战
1. 示例代码
示例代码定义了Counter计数器,有一个add()方法,每次增加随机值,总数保存在totalCount属性中。
Btracetest.java代码
package com.learnworld;
import java.util.Random;
public class BTraceTest {
public static void main(String[] args) throws Exception {
Random random = new Random();
// 计数器
Counter counter = new Counter();
while (true) {
// 每次增加随机值
counter.add(random.nextInt(10));
Thread.sleep(1000);
}
}
}
package com.learnworld; import java.util.Random; public class BTraceTest { public static void main(String[] args) throws Exception { Random random = new Random(); // 计数器 Counter counter = new Counter(); while (true) { // 每次增加随机值 counter.add(random.nextInt(10)); Thread.sleep(1000); } } }
Counter.java代码
package com.learnworld;
public class Counter {
// 总数
private static int totalCount = 0;
public int add(int num) throws Exception {
totalCount += num;
sleep();
return totalCount;
}
public void sleep() throws Exception {
Thread.sleep(1000);
}
}
package com.learnworld; public class Counter { // 总数 private static int totalCount = 0; public int add(int num) throws Exception { totalCount += num; sleep(); return totalCount; } public void sleep() throws Exception { Thread.sleep(1000); } }
2. 常见使用场景
下面通过几个常见使用场景演示如何使用BTrace脚本。
1) 获取add()方法参数值和返回值。
Java代码
import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.*; @BTrace public class TracingScript { @OnMethod( clazz="com.learnworld.Counter", method="add", location=@Location(Kind.RETURN) ) public static void traceExecute(int num,@Return int result){ println("====== "); println(strcat("parameter num: ",str(num))); println(strcat("return value:",str(result))); } }
import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.*; @BTrace public class TracingScript { @OnMethod( clazz="com.learnworld.Counter", method="add", location=@Location(Kind.RETURN) ) public static void traceExecute(int num,@Return int result){ println("====== "); println(strcat("parameter num: ",str(num))); println(strcat("return value:",str(result))); } }
2) 定时获取Counter类的属性值totalCount。
Java代码
import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.*; @BTrace public class TracingScript { private static Object totalCount = 0; @OnMethod( clazz="com.learnworld.Counter", method="add", location=@Location(Kind.RETURN) ) public static void traceExecute(@Self com.learnworld.Counter counter){ totalCount = get(field("com.learnworld.Counter","totalCount"), counter); } @OnTimer(1000) public static void print(){ println("====== "); println(strcat("totalCount: ",str(totalCount))); } }
import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.*; @BTrace public class TracingScript { private static Object totalCount = 0; @OnMethod( clazz="com.learnworld.Counter", method="add", location=@Location(Kind.RETURN) ) public static void traceExecute(@Self com.learnworld.Counter counter){ totalCount = get(field("com.learnworld.Counter","totalCount"), counter); } @OnTimer(1000) public static void print(){ println("====== "); println(strcat("totalCount: ",str(totalCount))); } }
3) 获取add方法执行时间。
Java代码
import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.*; @BTrace public class TracingScript { @TLS private static long startTime = 0; @OnMethod( clazz="com.learnworld.Counter", method="add" ) public static void startExecute(){ startTime = timeNanos(); } @OnMethod( clazz="com.learnworld.Counter", method="add", location=@Location(Kind.RETURN) ) public static void endExecute(@Duration long duration){ long time = timeNanos() - startTime; println(strcat("execute time(nanos): ", str(time))); println(strcat("duration(nanos): ", str(duration))); } }
import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.*; @BTrace public class TracingScript { @TLS private static long startTime = 0; @OnMethod( clazz="com.learnworld.Counter", method="add" ) public static void startExecute(){ startTime = timeNanos(); } @OnMethod( clazz="com.learnworld.Counter", method="add", location=@Location(Kind.RETURN) ) public static void endExecute(@Duration long duration){ long time = timeNanos() - startTime; println(strcat("execute time(nanos): ", str(time))); println(strcat("duration(nanos): ", str(duration))); } }
4) 获取add()方法调用方法sleep()次数。
Java代码
import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;
@BTrace
public class TracingScript {
private static long count;
@OnMethod(
clazz="/.*/",
method="add",
location=@Location(value=Kind.CALL, clazz="/.*/", method="sleep")
)
public static void traceExecute(@ProbeClassName String pcm, @ProbeMethodName String pmn,
@TargetInstance Object instance, @TargetMethodOrField String method){
println("====== ");
println(strcat("ProbeClassName: ",pcm));
println(strcat("ProbeMethodName: ",pmn));
println(strcat("TargetInstance: ",str(classOf(instance))));
println(strcat("TargetMethodOrField : ",str(method)));
count++;
}
@OnEvent
public static void getCount(){
println(strcat("count: ", str(count)));
}
}
import com.sun.btrace.annotations.*; import static com.sun.btrace.BTraceUtils.*; @BTrace public class TracingScript { private static long count; @OnMethod( clazz="/.*/", method="add", location=@Location(value=Kind.CALL, clazz="/.*/", method="sleep") ) public static void traceExecute(@ProbeClassName String pcm, @ProbeMethodName String pmn, @TargetInstance Object instance, @TargetMethodOrField String method){ println("====== "); println(strcat("ProbeClassName: ",pcm)); println(strcat("ProbeMethodName: ",pmn)); println(strcat("TargetInstance: ",str(classOf(instance)))); println(strcat("TargetMethodOrField : ",str(method))); count++; } @OnEvent public static void getCount(){ println(strcat("count: ", str(count))); } }
参考资料:
/article/3940863.html
http://www.linuxidc.com/Linux/2012-12/76155.htm
/article/5888880.html
/article/7606767.html
/article/3783623.html
/content/2744804.html
相关文章推荐
- 利用btrace工具监控在线运行java程序
- 利用jdk自带的运行监控工具JConsole观察分析Java程序的运行
- 利用jdk自带的运行监控工具JConsole观察分析Java程序的运行
- 利用jdk自带的运行监控工具JConsole观察分析Java程序的运行 Jtop
- 利用jdk自带的运行监控工具JConsole观察分析Java程序的运行
- 利用jdk自带的运行监控工具JConsole观察分析Java程序的运行
- 利用jdk自带的运行监控工具JConsole观察分析Java程序的运行
- 利用jdk自带的运行监控工具JConsole观察分析Java程序的运行
- java系统运维:使用java自带的工具监控系统(java)虚机的运行
- 使用JRockit Mission Control监控Java程序运行性能
- java 性能监控 jstack 线程死锁 JConsole 和 BTrace 图形化工具
- 利用btrace在线监控java程序状态
- Java VisualVM 监控远程Java程序运行情况
- HouseMD, 比BTrace更实用的Java运行诊断工具
- 采用JDK工具编译运行java程序
- 使用JRockit Mission Control监控Java程序运行性能
- 飞鸽快信微信消息-LINUX服务器告警、状态监控预警、程序报警提醒等消息实时推送工具
- 利用btrace在线监控java程序状态
- 构建自己的监测器【1】-监测工具 注:监控java代码运行情况
- 我工作这几年(五)-- 在代码中加入一些关键统计信息来实时监控程序的运行状态