在周志明老師的深刻理解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(); } }