用btrace定位问题

btrace 截取方法出入参

用btrace的手法,网上有很多。简单记录下我自己的使用经历。

btrace脚本:

import static com.sun.btrace.BTraceUtils.exit;  
import static com.sun.btrace.BTraceUtils.field;  
import static com.sun.btrace.BTraceUtils.get;  
import static com.sun.btrace.BTraceUtils.jstack;  
import static com.sun.btrace.BTraceUtils.printEnv;  
import static com.sun.btrace.BTraceUtils.printFields;  
import static com.sun.btrace.BTraceUtils.printProperties;  
import static com.sun.btrace.BTraceUtils.printVmArguments;  
import static com.sun.btrace.BTraceUtils.println;  
  
  
import com.sun.btrace.BTraceUtils.Strings;  
import com.sun.btrace.BTraceUtils.Sys;  
import com.sun.btrace.annotations.BTrace;  
import com.sun.btrace.annotations.Duration;  
import com.sun.btrace.annotations.Kind;  
import com.sun.btrace.annotations.Location;  
import com.sun.btrace.annotations.OnMethod; 
import com.sun.btrace.annotations.Return;   
import com.sun.btrace.annotations.Self;  

import static com.sun.btrace.BTraceUtils.*; 
  
  
@BTrace  
public class t {  
  
  
//print System Properties:  
static {  
println("System Properties:");  
printProperties();  
println("VM Flags:");  
printVmArguments();  
println("OS Enviroment:");  
printEnv();  
exit(0);  
}  
  
    @OnMethod(clazz = "com.xxxxxxx.FlowServiceImpl", method = "queryFlowList",location=@Location(Kind.RETURN))  
    public static void traceStoreInTransactionExecute(java.util.Map<String, Object> content, java.lang.Integer iDisplayStart,
        java.lang.Integer iDisplayLength,  @Return java.util.List<com.xxxxxxxx.ScenarioJournalBo> ret) {  
    println(str(ret));
    println(str(content));
    println(str(iDisplayStart));   
    println(str(iDisplayLength));   
    }  
  
 
  
}

此处脚本 用于监控方法入参,和出参.

监控性能

用于监控性能,执行某个方法的时间消耗,单位是纳秒 换成毫秒要除以1000000

这个比一般写代码去监控好用些,毕竟只是配置一下

import static com.sun.btrace.BTraceUtils.exit;
import static com.sun.btrace.BTraceUtils.field;
import static com.sun.btrace.BTraceUtils.get;
import static com.sun.btrace.BTraceUtils.jstack;
import static com.sun.btrace.BTraceUtils.printEnv;
import static com.sun.btrace.BTraceUtils.printFields;
import static com.sun.btrace.BTraceUtils.printProperties;
import static com.sun.btrace.BTraceUtils.printVmArguments;
import static com.sun.btrace.BTraceUtils.println;

import com.sun.btrace.BTraceUtils.Strings;
import com.sun.btrace.BTraceUtils.Sys;
import com.sun.btrace.annotations.BTrace;
import com.sun.btrace.annotations.Duration;
import com.sun.btrace.annotations.Kind;
import com.sun.btrace.annotations.Location;
import com.sun.btrace.annotations.OnMethod;
import com.sun.btrace.annotations.Return;
import com.sun.btrace.annotations.Self;

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


@BTrace
public class SP02 {

@TLS private static long startTime;


//print System Properties:  
static {
println("System Properties:");
printProperties();
println("VM Flags:");
printVmArguments();
println("OS Enviroment:");
printEnv();
exit(0);
}

    // @OnMethod(clazz="com.xxxClass",method="beforeInvoke")
    //public static void onCall(){
     //   startTime=Time.millis();
//println("s");
   // }

    @OnMethod(clazz="com.xxxClass",method="processCall",location=@Location(Kind.RETURN))
    public static void onReturn(@Duration long d ){
        println(Strings.strcat("-processCall ", Strings.str(d)));
    }

    @OnMethod(clazz="com.xxxClass",method="updateSournal",location=@Location(Kind.RETURN))
    public static void onReturn1(@Duration long d ){
        println(Strings.strcat("-updateSnal ", Strings.str(d)));
    }

    @OnMethod(clazz="com.xxxClass",method="writeResponsR",location=@Location(Kind.RETURN))
    public static void onReturn2(@Duration long d ){
        println(Strings.strcat("-writeRR ", Strings.str(d)));
    }

    @OnMethod(clazz="org.springframework.web.servlet.DispatcherServlet",method="doDispatch",location=@Location(Kind.RETURN))
    public static void onReturn3(@Duration long d ){
        println(Strings.strcat("-doDispatch ", Strings.str(d)));
    }

    @OnMethod(clazz="com.xxx.AnnotationMethodHandlerAdapter",method="handle",location=@Location(Kind.RETURN))
    public static void onReturn4(@Duration long d ){
        println(Strings.strcat("-handle ", Strings.str(d)));
    }

}

执行

./btrace 25615 SP02.java
#25615 是你要监控的进程id(用jps可以看到)

注意:

1. 此手法若用于生产,最好在生产上包的时候 上btrace工具,因为不是jdk自带,不要要用的时候 找不到这个工具。

2. 如果btrace脚本中一来业务的类,则需要在执行的命令行中 指定classpath含有业务的jar(或者class目录)

3. 监控的脚本的类名需要与监控脚本文件名相同(与java代码一个规则。)

classpath问题 (以下段落均针对mac环境)

怎样快速的取classpath? 在linux/mac上都是  -classpath xx.jar全路径 冒号分隔 yy.jar全路径。但是如何快速的拿到这个classpath?在mac/linux上有个简单的办法,在你需要用btrace监听的工程中写个带有main方法的类,并不要让main方法结束,可以用

try
{
       System.in.read();
 }
  catch (IOException e)
{
      e.printStackTrace();
 }

也可以用Thread.sleep等办法。

然后用

ps -ef|grep "java">1.log

然后到1.log中就可以找到了所有依赖的jar构成的classpath信息了,准确快捷。

带有classpath的btrace使用示例是:

./btrace -classptah xxx/xx1.jar:xxx/xx2.jar 目标进程号 监听脚本类.java

JAVA_HOME问题

使用btrace需要设置JAVA_HOME环境变量 否则会报错:

Please set JAVA_HOME before running this script

我在mac设置是:

export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_121.jdk/Contents/Home

JAVA_VERSION问题

mac上使用btrace需要设置JAVA_VERSION环境变量,否则报错:

Please set JAVA_VERSION to the target java version

我的设置是:

export JAVA_VERSION=CurrentJDK

查找办法是:

看看这个路径System/Library/Frameworks/JavaVM.framework/Versions/${JAVA_VERSION}/Classes/classes.jar

报错:类文件具有错误的版本 52.0,应为 50.0

上面的jdk版本不对 导致了这个问题

重新设置:

export JAVA_HOME=/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
export JAVA_VERSION=1.6.0

至此能正常使用起来了

在研究btrace的过程中 发现了一个淘宝的 工具greys https://yq.aliyun.com/articles/2390

有空把玩一下。

原文地址:https://www.cnblogs.com/simoncook/p/6761853.html