- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) >
- Java運行時(shí)如何使用追蹤工具BTrace
這期內容當中小編將會(huì )給大家帶來(lái)有關(guān)Java運行時(shí)如何使用追蹤工具BTrace,文章內容豐富且以專(zhuān)業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
Btrace是由sundararajan在2009年6月開(kāi)發(fā)的一個(gè)開(kāi)源項目,是一種動(dòng)態(tài)跟蹤分析一個(gè)運行中的Java應用程序的工具。 BTrace是一個(gè)為Java平臺開(kāi)發(fā)的安全、動(dòng)態(tài)的追蹤工具。BTrace動(dòng)態(tài)地向目標應用程序的字節碼注入追蹤代碼(字節碼追蹤),這些追蹤字節碼追蹤代碼使用Java語(yǔ)言表達,也就是BTrace的腳本。
為了保證追蹤動(dòng)作是“只讀”的(也就是這些動(dòng)作不可以修改被追蹤程序的狀態(tài))和有限度的(比如在固定時(shí)間里結束)。一個(gè)BTrace程序只允許完成一些指定的動(dòng)作。下面是BTrace一些不可以完成的事情:
不能創(chuàng )建新的對象
不能創(chuàng )建新的數組
不能拋出異常
不能捕獲異常
不能進(jìn)行任何的實(shí)例函數或者靜態(tài)函數 – 只有com.sun.btrace.BTraceUtils類(lèi)中的靜態(tài)函數或者BTrace程序自己聲明的函數才可以被BTrace調用
不可以在目標程序的類(lèi),或者對象的靜態(tài)或者實(shí)例級別的field進(jìn)行賦值。但是,BTrace自身的類(lèi)是可以給它的靜態(tài)field進(jìn)行賦值的
不能有outer,inner,嵌套的或者本地類(lèi)。
不能有同步代碼塊或者同步的函數
不能有循環(huán)語(yǔ)句(for,while, do..while)
不能繼承其它類(lèi)(父類(lèi)只能是java.lang.Object)
不能實(shí)現接口
不能包含斷言(assert)語(yǔ)句
不能使用類(lèi)字面值
這上面的種種限制可以通過(guò)一個(gè)配置改變:unsafe=true,在使用BTrace注解時(shí)修改該屬性的默認值(false)為true,即@BTrace(unsafe=true);也可以啟動(dòng)選項中顯式聲明-Dcom.sun.btrace.unsafe=true(響應也有-u參數);現在你可以為所欲為了。BUT,這樣做之前最好考慮好風(fēng)險并再三檢查腳本,請斟酌使用!
btrace git下載地址 ,下載release版本下來(lái)直接解壓就可以使用。
btrace <pid> <btrace-script>腳本
btrace命令行工具運行命令如下:
btrace <options> <pid> <btrace source or .class file> <btrace arguments> 常用選項: [-I <include-path>] [-p <port>] [-cp <classpath>]
參數說(shuō)明:
where possible options include: --version Show the version -v Run in verbose mode -o <file> The path to store the probe output (will disable showing the output in console) -u Run in trusted mode -d <path> Dump the instrumented classes to the specified path -pd <path> The search path for the probe XML descriptors -classpath <path> Specify where to find user class files and annotation processors -cp <path> Specify where to find user class files and annotation processors -I <path> Specify where to find include files -p <port> Specify port to which the btrace agent listens for clients -statsd <host[:port]> Specify the statsd server, if any
include-path : 是一些用來(lái)查找頭文件的目錄。BTrace包含一個(gè)簡(jiǎn)單的預處理,支持# define,# + include和條件編譯。它不像一個(gè)完整的C / c++預處理器–而是一個(gè)有用的子集。詳見(jiàn)demo代碼“ThreadBean.java”,如果沒(méi)有顯式的聲明選項-I,Btrace跳過(guò)預處理程序調用步驟。
port: BTrace代理程序所偵聽(tīng)的端口,這是可選的選項。默認是2020
classpath: 是一些用來(lái)查找jar文件的目錄。默認是當前目錄”.”
pid:是要追蹤目標程序id
btrace-script: 就是追蹤程序本身。如果這是個(gè)java文件,那么提交前會(huì )進(jìn)行編譯。否則,它被認為已預編譯(即它必須是一個(gè)類(lèi))并提交
arguments: 這是傳遞給BTrace程序的參數。BTrace程序可以通過(guò)內置的符號來(lái)引用這些參數,length是這些參數的個(gè)數。
在samples目錄下有很多示例,并且有的跟蹤很有用可直接使用.
@com.sun.btrace.annotations.OnMethod 該注解可用來(lái)指定目標類(lèi),目標方法,以及目標方法里的“位置”。加了該注解后的操作方法會(huì )在對應的方法運行到指定的“位置”時(shí)被執行。該注解中,目標類(lèi)用“clazz”屬性來(lái)指定,而目標方法用“method”屬性來(lái)指定?!眂lazz”可以是類(lèi)的全路徑(比如java.awt.Component或者用兩個(gè)反斜杠中間的正則表達式,參考例子NewComponent.java和Classload.java來(lái)看它們的用法,正則表達式可以匹配0個(gè)或多個(gè)目標類(lèi),這個(gè)時(shí)候多個(gè)類(lèi)都會(huì )被進(jìn)行動(dòng)態(tài)指令更換。如/java.awt.+/匹配java.awt包下的所有類(lèi))。方法名也可以用這樣的正則表達式 來(lái)匹配零個(gè)或者多個(gè)多個(gè)方法。參考例子MultiClass.java來(lái)查看用法。還有一種方法來(lái)指定追蹤類(lèi)和函數。被追蹤的類(lèi)和函數可以用注解來(lái)指定。比如,如果”clazz”屬性是@javax.jws.Webservice.那么BTrace會(huì )會(huì )把所有注解是這個(gè)的函數都進(jìn)行動(dòng)態(tài)指令更換。類(lèi)似地,方法級別的注解也可以用來(lái)執行方法。參看例子WebServiceTracker.java來(lái)了解如何使用??梢园颜齽t表達式和注解放在一起用,比如@/com.acme..+/可以匹配任何類(lèi),只要這個(gè)類(lèi)的注解能跟那段正則表達式匹配即可??梢酝ㄟ^(guò)指定父類(lèi)來(lái)匹配多個(gè)類(lèi)名,比如+java.lang.Runnable就可以匹配所有實(shí)現了java.lang.Runnable這個(gè)接口的類(lèi)。參考例子SubtypeTracer.java來(lái)看它的用法。
@com.sun.btrace.annotations.OnTimer 該注解可以用來(lái)執行那些需要周期性(間隔是毫秒)的追蹤操作。參考Histogram.java來(lái)看它的用法。
@com.sun.btrace.annotations.OnError 該注解可以用來(lái)指定當任何異常拋出時(shí)需要執行的操作。被該注解修飾后的BTrace函數會(huì )在同一個(gè)BTrace類(lèi)的其他操作方法拋出異常時(shí)執行。
@com.sun.btrace.annotations.OnExit 該注解用來(lái)執行黨BTrace代碼調用了exit(int)結束追蹤會(huì )話(huà)后需要執行的操作。參考例子ProbeExit.java來(lái)了解如何使用。
@com.sun.btrace.annotations.OnEvent 該注解用來(lái)追蹤函數與”外部”的事件關(guān)聯(lián)起來(lái)。當BTrace客戶(hù)端發(fā)送了一個(gè)“事件”后,該注解里的操作就會(huì )被執行??蛻?hù)端發(fā)送的事件可能是由用戶(hù)觸發(fā)的(比如按下Ctrl-C)。事件的名字是個(gè)字符串,這樣追蹤操作就只會(huì )在對應的事件觸發(fā)后被執行。到目標為止,BTrace命令行客戶(hù)端會(huì )在用戶(hù)按下Ctrl-C后發(fā)送事件,參考例子HistoOnEvent.java來(lái)了解用法。
@com.sun.btrace.annotations.OnLowMemory 該注解可以用來(lái)追蹤特定內存閾值被用光的事件。參看例子MemAlerter.java了解用法。
@com.sun.btrace.annotations.OnProbe 該注解可以用來(lái)避免使用BTrace腳本的內部類(lèi)。@OnProbe探測點(diǎn)被映射到一個(gè)或多個(gè)@OnMethod上。目前這個(gè)映射是通過(guò)一個(gè)XML探測描述文件類(lèi)指定的(這個(gè)文件會(huì )被BTrace代理所使用)。參考例子SocketTracker1.java和對應的描述文件java.net.socket.xml.當運行這個(gè)例子時(shí),xml文件需要放在目標JVM所有運行的目錄下(或者修改btracer.bat中的probeDescPath選項來(lái)指向任意的xml文件)。
@com.sun.btrace.annotations.Location:該注解在一個(gè)traced/probed方法中指定一個(gè)特定的“位置”
@com.sun.btrace.annotations.Simpled:標記@OnMethod注解處理器采樣。采樣處理程序時(shí)并不是所有的事件將被追蹤,只有一個(gè)統計樣品與給定的意思。在默認情況下使用一種自適應采樣。BTrace將增加或減少樣品之間的調用數量保持平均時(shí)間窗口,因此減少整體的開(kāi)銷(xiāo)。
@com.sun.btrace.annotations.Self:該注解把一個(gè)參數標識為保留了目標函數所指向的this的值。參考例子AWTEventTracer.java和AllCalls1.java.
@com.sun.btrace.annotations.Return:該注解說(shuō)明這個(gè)參數保存目標函數的返回值。參考例子Classload.java
@com.sun.btrace.annotations.ProbeClassName:所修飾的參數保留了探測類(lèi)的類(lèi)名 。參看AllMethods.java(有多個(gè)探測類(lèi))
@com.sun.btrace.annotations.ProbeMethodName:所修飾的參數保留了探測函數的函數名。參考WebServiceTracker.java(多個(gè)探測函數)
@com.sun.btrace.annotations.TargetInstance:修飾的參數保留了被調用的實(shí)例。參考例子AllCall2.java.
@com.sun.btrace.annotations.TargetMethodOrField:該注解修飾的參數保存了調用的函數名。參考AllCalls1.java 和AllCall2.java
@com.sun.btrace.annotations.Duration:探測方法參數標記為持續時(shí)間值的接收者,即目標方法執行的時(shí)間,單位納秒。只是用帶Location屬性的@OnMethod,并且需要配合Kind.ERROR或者Kind.RETURN使用
沒(méi)有注解的BTrace探測函數參數是用來(lái)作簽名匹配的,因為他們必須必須在固定的位置上出現。然而,它們可以和其他的注解的參數進(jìn)行交換。如果一個(gè)參數的類(lèi)型是_AnyType[]_,它就會(huì )“吃”掉所所有剩下的參數。沒(méi)有注解的參數的具體含義與他們所在的位置有關(guān):
@com.sun.btrace.annotations.Export BTrace字段使用該注解來(lái)說(shuō)明它已經(jīng)被映射到一個(gè)jvmstat計數器上。使用該注解,BTrace程序可以把追蹤計數器暴露給外部的jvmstat客戶(hù)端(比如jstat)。參考例子ThreadCounter.java
@com.sun.btrace.annotations.Property 該注解可以把一個(gè)字段標識為一個(gè)MBean屬性。如果一個(gè)BTrace類(lèi)至少有一個(gè)靜態(tài)的字段使用了該注解。那么一個(gè)MBean就會(huì )被創(chuàng )建并且注冊到平臺MBean上。JMX客戶(hù)端比如VisualVM,jconsole可以訪(fǎng)問(wèn)這個(gè)字段來(lái)查看BTrace的MBean。在把BTrace附加到目標程序上后,你可以把VisualVM或者jconsole也附加到同一個(gè)目標程序上來(lái)查看剛創(chuàng )建好的MBean屬性。通過(guò)VisualVM或者jconsole,你可以通過(guò)MBeans tab頁(yè)來(lái)查看BTrace相關(guān)的域,然后查看它們的值。參考例子ThreadCounterBean.java 和HistogramBean.java來(lái)了解用法
@com.sun.btrace.annotations.TLS BTrace字段使用該注解來(lái)說(shuō)明它自己是一個(gè)線(xiàn)程本地字段(thread local field).注意你只能在@OnMethod注解后的函數里訪(fǎng)問(wèn)這樣的字段。每個(gè)Java線(xiàn)程都有一個(gè)這個(gè)字段的拷貝。為了讓這樣的方式能夠工作,這個(gè)字段的類(lèi)型只能是immutable(比如原始類(lèi)型) 或者是cloneable (實(shí)現了Cloneable接口并且覆蓋了clone()函數)的。這些線(xiàn)程本地字段可以被BTrace程序用來(lái)識別它是否在同一個(gè)線(xiàn)程里執行了多個(gè)探測操作。參考例子OnThrow.java和WebServiceTracker.java
@com.sun.btrace.annotations.DTrace該注解用來(lái)把一小段D腳本(嵌在BTrace 的java類(lèi)中)和BTrace程序關(guān)聯(lián)起來(lái)。參考例子DTraceInline.java
@com.sun.btrace.annotations.DTraceRef 和上個(gè)注解一樣,不同的是D腳本是在獨立的文件中,不是嵌在java類(lèi)中。
@com.sun.btrace.annotations.BTrace必須使用該注解來(lái)指定一個(gè)Java類(lèi)是BTrace程序。BTrace編譯器會(huì )強制查找該注解,BTrace代理也會(huì )檢查這個(gè)是否有該注解。如果沒(méi)有,則提示錯誤,并且不會(huì )執行。
package com.gitee.funcy.jtools.btrace; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; /** * 該程序周期性地進(jìn)行網(wǎng)絡(luò )讀取操作 * * @author chengyan * @date 2019-11-03 10:41 下午 */ public class HoldNetTask implements Runnable{ public void visitWeb(String strUrl) { URL url = null; URLConnection urlconn = null; InputStream is = null; try { url = new URL(strUrl); urlconn = url.openConnection(); is = urlconn.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is)); StringBuffer bs = new StringBuffer(); String l = null; while((l = bufferedReader.readLine()) != null) { bs.append(l).append("\r\n"); } } catch (Exception e) { e.printStackTrace(); } finally { if(is != null) { try { is.close(); } catch (Exception e) { } } } } @Override public void run() { while(true) { visitWeb("http://www.sina.com.cn"); } } public static void main(String[] args) { new Thread(new HoldNetTask()).start(); } }
BTrace對應的java包在Btrace release文件的build目錄下,一共有三個(gè)jar包:
btrace-agent.jar btrace-boot.jar btrace-client.jar
也可使用maven引入依賴(lài)包,在pom文件中添加以下內容:
<properties> ...省略其他 <btrace.version>1.3.11.3</btrace.version> </properties> <dependencies> ...省略其他 <dependency> <groupId>com.sun.tools.btrace</groupId> <artifactId>btrace-agent</artifactId> <version>${btrace.version}</version> </dependency> <dependency> <groupId>com.sun.tools.btrace</groupId> <artifactId>btrace-boot</artifactId> <version>${btrace.version}</version> </dependency> <dependency> <groupId>com.sun.tools.btrace</groupId> <artifactId>btrace-client</artifactId> <version>${btrace.version}</version> </dependency> </dependencies> <repositories> <repository> <id>btrace-repo</id> <name>btrace-repo</name> <url>https://dl.bintray.com/btraceio/maven/</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
需要注意的是,maven中央倉庫中可能沒(méi)有btrace的最新版本,為此需要配置額外的倉庫。
使用BTrace腳本可以通過(guò)正則表達式指定監控特定類(lèi)的特定方法的耗時(shí),以下代碼將監控所有類(lèi)中名為visitWeb()
的函數的執行時(shí)間。
package com.gitee.funcy.jtools.btrace; 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.ProbeClassName; import com.sun.btrace.annotations.ProbeMethodName; import com.sun.btrace.annotations.TLS; import static com.sun.btrace.BTraceUtils.*; /** * {這里添加描述} * * @author chengyan * @date 2019-11-03 12:13 上午 */ @BTrace public class PrintTimes { @TLS private static long startTime = 0; /** * 方法調用開(kāi)始 * clazz = "/.+/" : 監控做任意類(lèi) * method="/visitWeb/":監控visitWeb方法 */ @OnMethod(clazz = "/.+/", method="/visitWeb/") public static void startMethod() { startTime = timeMillis(); } @OnMethod(clazz = "/.+/", method="/visitWeb/", location=@Location(Kind.RETURN)) public static void endMethod(@ProbeClassName String pcm, @ProbeMethodName String pmn) { println(pcm + "." + pmn + " [Time taken: " + str(timeMillis() - startTime) + "ms]"); } }
運行結果:
$ btrace 42188 PrintTimes.java com.gitee.funcy.jtools.btrace.HoldNetTask.visitWeb [Time taken: 55ms] com.gitee.funcy.jtools.btrace.HoldNetTask.visitWeb [Time taken: 50ms] com.gitee.funcy.jtools.btrace.HoldNetTask.visitWeb [Time taken: 52ms] com.gitee.funcy.jtools.btrace.HoldNetTask.visitWeb [Time taken: 49ms] com.gitee.funcy.jtools.btrace.HoldNetTask.visitWeb [Time taken: 54ms] com.gitee.funcy.jtools.btrace.HoldNetTask.visitWeb [Time taken: 54ms]
除了執行時(shí)間,BTrace也可輸出函數的參數:
package com.gitee.funcy.jtools.btrace; import com.sun.btrace.AnyType; import com.sun.btrace.BTraceUtils; import com.sun.btrace.annotations.BTrace; import com.sun.btrace.annotations.OnMethod; import com.sun.btrace.annotations.ProbeClassName; import com.sun.btrace.annotations.ProbeMethodName; /** * {這里添加描述} * * @author chengyan * @date 2019-11-03 10:43 下午 */ @BTrace public class PrintArgs { @OnMethod(clazz = "/.*HoldNetTask/",method = "/visitWeb/") public static void anyWriteFile(@ProbeClassName String pcn, @ProbeMethodName String pmn, AnyType[] args) { BTraceUtils.print(pcn + "-" + pmn); BTraceUtils.printArray(args); } }
運行結果:
$ btrace 46877 PrintArgs.java com.gitee.funcy.jtools.btrace.HoldNetTask-visitWeb[http://www.sina.com.cn, ] com.gitee.funcy.jtools.btrace.HoldNetTask-visitWeb[http://www.sina.com.cn, ] com.gitee.funcy.jtools.btrace.HoldNetTask-visitWeb[http://www.sina.com.cn, ] com.gitee.funcy.jtools.btrace.HoldNetTask-visitWeb[http://www.sina.com.cn, ] com.gitee.funcy.jtools.btrace.HoldNetTask-visitWeb[http://www.sina.com.cn, ] com.gitee.funcy.jtools.btrace.HoldNetTask-visitWeb[http://www.sina.com.cn, ]
通過(guò)BTrace腳本@Location
注解,可以指定程序運行到某一行代碼時(shí),觸發(fā)某一行為。下例顯示了通過(guò)BTrace腳本獲取HoldNetTask
類(lèi)第27行代碼的信息(當目標程序運行到第27行時(shí),觸發(fā)BTrace腳本)。
package com.gitee.funcy.jtools.btrace; import static com.sun.btrace.BTraceUtils.*; import com.sun.btrace.annotations.BTrace; import com.sun.btrace.annotations.Location; import com.sun.btrace.annotations.OnMethod; import com.sun.btrace.annotations.Kind; import com.sun.btrace.annotations.ProbeClassName; import com.sun.btrace.annotations.ProbeMethodName; /** * {這里添加描述} * * @author chengyan * @date 2019-11-04 10:02 下午 */ @BTrace public class AllLines { @OnMethod(clazz = "/.*HoldNetTask/", location = @Location(value = Kind.LINE, line = 27)) public static void online(@ProbeClassName String pcn, @ProbeMethodName String pmn, int line) { println(pcn + "." + pmn + ":" + line); } }
運行結果:
$ btrace 46877 AllLines.java com.gitee.funcy.jtools.btrace.HoldNetTask.visitWeb:27 com.gitee.funcy.jtools.btrace.HoldNetTask.visitWeb:27 com.gitee.funcy.jtools.btrace.HoldNetTask.visitWeb:27 com.gitee.funcy.jtools.btrace.HoldNetTask.visitWeb:27 com.gitee.funcy.jtools.btrace.HoldNetTask.visitWeb:27 com.gitee.funcy.jtools.btrace.HoldNetTask.visitWeb:27
由腳本輸出可以看到,BTrace正確識別出HoldNetTask類(lèi)的第27行代碼,正處于visitWeb()
函數的運行區間中。若將 @Location
中line的值設置為-1,則BTrace腳本將在每一行觸發(fā)。
BTrace腳本支持定時(shí)觸發(fā)??梢灾芷谛缘貓绦心骋恍袨?,獲取系統信息。下例使用@OnTimer
標記制定兩個(gè)周期性任務(wù),分別為每秒運行一次和每3秒運行一次。
package com.gitee.funcy.jtools.btrace; import com.sun.btrace.BTraceUtils; import com.sun.btrace.annotations.BTrace; import com.sun.btrace.annotations.OnTimer; import static com.sun.btrace.BTraceUtils.jstackAll; import static com.sun.btrace.BTraceUtils.println; /** * {這里添加描述} * * @author chengyan * @date 2019-11-04 10:11 下午 */ @BTrace public class Timers { @OnTimer(1000) public static void getUpTime() { println(BTraceUtils.Strings.strcat("1000 msec:", BTraceUtils.Strings.str(BTraceUtils.Sys.VM.vmUptime()))); } @OnTimer(3000) public static void getStack() { jstackAll(); } }
運行結果:
$ btrace 46969 Timers.java 1000 msec:27654 1000 msec:28647 Thread[Attach Listener,9,system] Thread[Signal Dispatcher,9,system] Thread[Thread-1,9,system] java.net.PlainSocketImpl.socketAccept(Native Method) java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409) java.net.ServerSocket.implAccept(ServerSocket.java:545) java.net.ServerSocket.accept(ServerSocket.java:513) com.sun.btrace.agent.Main.startServer(Main.java:668) com.sun.btrace.agent.Main.access$000(Main.java:63) com.sun.btrace.agent.Main$2.run(Main.java:128) java.lang.Thread.run(Thread.java:748)
在getUpTime()
方法中,指定了一個(gè)每秒運行一次的任務(wù),并打印虛擬機的啟動(dòng)時(shí)間。在getStack()
方法中,指定了一個(gè)每3秒運行一次的任務(wù),每次都將導出系統的線(xiàn)程快照。
在程序運行過(guò)程中,BTrace可以在指定的位置獲得對象實(shí)例的字段信息。比如,在本實(shí)例中,可以在調用URL.openConnection()
時(shí)查看實(shí)際打開(kāi)的URL地地址。
package com.gitee.funcy.jtools.btrace; import com.sun.btrace.annotations.BTrace; import com.sun.btrace.annotations.Location; import com.sun.btrace.annotations.OnMethod; import com.sun.btrace.annotations.Kind; import com.sun.btrace.annotations.ProbeClassName; import com.sun.btrace.annotations.ProbeMethodName; import com.sun.btrace.annotations.Self; import static com.sun.btrace.BTraceUtils.*; /** * {這里添加描述} * * @author chengyan * @date 2019-11-04 10:20 下午 */ @BTrace public class PrintField { @OnMethod(clazz = "/.*URL/", method = "/.*openConnection/", location = @Location(value = Kind.ENTRY)) public static void visitWebEntry(@Self Object self, @ProbeClassName String pcn, @ProbeMethodName String pmn) { println(pcn + "." + pmn); println(self); // 只能取值static變量 println(get(field(classOf(self), "protocolPathProp"))); // 獲得實(shí)例變量 println(get(field(classOf(self), "host"), self)); println("==============="); } }
運行結果:
$ btrace 46969 PrintField.java java.net.URL.openConnection http://www.sina.com.cn java.protocol.handler.pkgs www.sina.com.cn ===============
這里監控URL對象,在調用openConnection()
方法時(shí),獲得當前對象實(shí)例self,然后獲取對應實(shí)例的host等屬性。
腳本中方法參數需要跟原方法參數類(lèi)型保持一致
腳本中不允許使用除btrace之外的類(lèi),拼接字符串使用BTraceUtils.strcat()
,打印使用BTraceUtils.println()
,獲取線(xiàn)程使用BTraceUtils.Threads
BTrace植入過(guò)的代碼,會(huì )一直在,直到應用重啟為止。所以即使Btrace退出了,業(yè)務(wù)函數每次執行時(shí)都會(huì )執行Btrace植入的代碼
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。
Copyright ? 2009-2021 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 珠海市特網(wǎng)科技有限公司 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站