在周志明老师的深刻理解JVM虚拟机一书中,周老师这样描述Btrace:在不中止目标程序运行的状况下,经过HotSpot虚拟机的HotSwap技术动态加入本来并不存在的调试代码。从这段话,咱们能够获得如下信息:1.使用Btrace能够在不中止程序的状况下进行调试。2.应用于HotSpot虚拟机,若是是其余虚拟机,是不能用的。java
项目地址git
项目结构github
pom.xmlweb
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.7.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>zte.hdh</groupId> <artifactId>monitor_tuning</artifactId> <version>0.0.1-SNAPSHOT</version> <name>monitor_tuning</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>asm</groupId> <artifactId>asm</artifactId> <version>3.3.1</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.58</version> </dependency> <dependency> <groupId>com.sun.btrace</groupId> <artifactId>btrace-agent</artifactId> <version>1.3.11.3</version> <type>jar</type> <scope>system</scope> <systemPath>D:\ImportantDevTools\btrace-bin-1.3.11.3\build\btrace-agent.jar</systemPath> </dependency> <dependency> <groupId>com.sun.btrace</groupId> <artifactId>btrace-boot</artifactId> <version>1.3.11.3</version> <type>jar</type> <scope>system</scope> <systemPath>D:\ImportantDevTools\btrace-bin-1.3.11.3\build\btrace-boot.jar</systemPath> </dependency> <dependency> <groupId>com.sun.btrace</groupId> <artifactId>btrace-client</artifactId> <version>1.3.11.3</version> <type>jar</type> <scope>system</scope> <systemPath>D:\ImportantDevTools\btrace-bin-1.3.11.3\build\btrace-client.jar</systemPath> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
测试类(被拦截)
BTraceOneController.java:spring
package zte.hdh.btrace; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/btrace1") public class BTraceOneController { @RequestMapping("/arg1") public String arg1(@RequestParam("name") String name) { return "hello," + name; } }
Btrace类
BTraceArgSimple.java:apache
package zte.hdh.btrace; import com.sun.btrace.AnyType; import com.sun.btrace.BTraceUtils; import com.sun.btrace.annotations.*; @BTrace public class BTraceArgSimple { @OnMethod( clazz="zte.hdh.btrace.BTraceOneController",//拦截的方类 method="arg1",//拦截的方法 location=@Location(Kind.ENTRY)//拦截的实际 ) public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args) {//AnyType[] args意思是全部参数,若是方法有两个参数String int,那么这里就可写String arg1,int arg2 BTraceUtils.printArray(args); BTraceUtils.println(pcn); BTraceUtils.println(pmn); BTraceUtils.println(); } }
启动应用后,获取pid,到btrace脚本BTraceArgSimple.java的位置,运行btrace 48284 BTraceArgSimple.java,开始监控咱们的程序。在浏览器中输入:http://localhost:8080/btrace1/arg1?name=hdh,那么运行btrace脚本的控制台将输出拦截的参数、类和方法等信息:json
PrintReturn.java浏览器
package zte.hdh.btrace; import com.sun.btrace.AnyType; import com.sun.btrace.BTraceUtils; import com.sun.btrace.annotations.*; @BTrace public class PrintReturn { @OnMethod( clazz="zte.hdh.btrace.BTraceOneController", method="arg1", location=@Location(Kind.RETURN) ) public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, @Return AnyType result) { BTraceUtils.println(pcn + ", " + pmn + "," + result); BTraceUtils.println(); } }
BTraceOneController.java中增长一个rest接口:app
@RequestMapping("/exception") public String exception() { try { System.out.println("start..."); System.out.println(1/0); System.out.println("end..."); }catch(Exception e) { //忘记打印出异常 } return "success"; }
btrace类PrintOnThrow.java:maven
package zte.hdh.btrace; import com.sun.btrace.BTraceUtils; import com.sun.btrace.annotations.*; @BTrace public class PrintOnThrow { // store current exception in a thread local // variable (@TLS annotation). Note that we can't // store it in a global variable! @TLS static Throwable currentException; // introduce probe into every constructor of java.lang.Throwable // class and store "this" in the thread local variable. @OnMethod( clazz="java.lang.Throwable", method="<init>" ) public static void onthrow(@Self Throwable self) {//拦截new Throwable() currentException = self; } @OnMethod( clazz="java.lang.Throwable", method="<init>" ) public static void onthrow1(@Self Throwable self, String s) {//拦截new Throwable(String msg) currentException = self; } @OnMethod( clazz="java.lang.Throwable", method="<init>" ) public static void onthrow1(@Self Throwable self, String s, Throwable cause) {//拦截new Throwable(String msg, Throwable cause) currentException = self; } @OnMethod( clazz="java.lang.Throwable", method="<init>" ) public static void onthrow2(@Self Throwable self, Throwable cause) {//拦截new Throwable(Throwable cause) currentException = self; } // when any constructor of java.lang.Throwable returns // print the currentException's stack trace. @OnMethod( clazz="java.lang.Throwable", method="<init>", location=@Location(Kind.RETURN) ) public static void onthrowreturn() { if (currentException != null) { //打印整个异常堆栈 BTraceUtils.Threads.jstack(currentException); BTraceUtils.println("====================="); currentException = null; } } }
package zte.hdh.btrace; import com.sun.btrace.BTraceUtils; import com.sun.btrace.annotations.*; @BTrace public class PrintLine { @OnMethod( clazz="com.example.demo.btrace.Ch4Controller", method="exception", location=@Location(value= Kind.LINE, line=40) ) public static void anyRead(@ProbeClassName String pcn, @ProbeMethodName String pmn, int line) { BTraceUtils.println(pcn + ", " + pmn + "," + line); BTraceUtils.println(); } }