監(jiān)控的基本流程
基本流程
采集數(shù)據(jù)的方式
- 有代碼侵入(比如:Cat);
- 無(wú)代碼侵入(比如:Skywalking、Pinpoint等);
怎么做到無(wú)代碼侵入?
JVMTI(JAVA Virtual machine Tool Interface)是一套由 Java 虛擬機(jī)提供的,為 JVM 相關(guān)的工具提供的本地編程接口集合。JVMTI 是從 Java SE 5 開(kāi)始引入,整合和取代了以前使用的 Java Virtual Machine Profiler Interface (JVMPI) 和 the Java Virtual Machine Debug Interface (JVMDI),而在 Java SE 6 中,JVMPI 和 JVMDI 已經(jīng)消失了。JVMTI 提供了一套”代理”程序機(jī)制,可以支持第三方工具程序以代理的方式連接和訪問(wèn) JVM,并利用 JVMTI 提供的豐富的編程接口,完成很多跟 JVM 相關(guān)的功能。事實(shí)上,java.lang.instrument 包的實(shí)現(xiàn),也就是基于這種機(jī)制的:在 Instrumentation 的實(shí)現(xiàn)當(dāng)中,存在一個(gè) JVMTI 的代理程序,通過(guò)調(diào)用 JVMTI 當(dāng)中 Java 類相關(guān)的函數(shù)來(lái)完成 Java 類的動(dòng)態(tài)操作。除開(kāi) Instrumentation 功能外,JVMTI 還在虛擬機(jī)內(nèi)存管理,線程控制,方法和變量操作等等方面提供了大量有價(jià)值的函數(shù)。
使用 JVMTI 我們能做兩件事:
- 在虛擬機(jī)啟動(dòng)時(shí),即在main方法之前可以做一些事情(通過(guò) Java agent);
- 在虛擬機(jī)啟動(dòng)之后,即在main方法之后可以做一些事情(通過(guò) Attach API);
Java agent的作用(探針)
javaagent是一個(gè)命令,用來(lái)監(jiān)測(cè)和協(xié)助運(yùn)行在 JVM 上的程序,甚至能夠替換和修改某些類的定義。有了這樣的功能,開(kāi)發(fā)者就可以實(shí)現(xiàn)更為靈活的運(yùn)行時(shí)虛擬機(jī)監(jiān)控和 Java 類操作了,這樣的特性實(shí)際上提供了一種虛擬機(jī)級(jí)別支持的 AOP 實(shí)現(xiàn)方式,使得開(kāi)發(fā)者無(wú)需對(duì) JDK 做任何升級(jí)和改動(dòng),就可以實(shí)現(xiàn)某些 AOP 的功能了。
Java agent的使用
通過(guò) java.lang.instrument.Instrumentation 來(lái)實(shí)現(xiàn)。
1.編寫(xiě)premain函數(shù)
public static void premain(String agentArgs, Instrumentation inst); [1] public static void premain(String agentArgs); [2]
其中,[1] 的優(yōu)先級(jí)比 [2] 高,將會(huì)被優(yōu)先執(zhí)行([1] 和 [2] 同時(shí)存在時(shí),[2] 被忽略)。
在這個(gè) premain 函數(shù)中,開(kāi)發(fā)者可以進(jìn)行對(duì)類的各種操作。
agentArgs 是 premain 函數(shù)得到的程序參數(shù),隨同 “– javaagent”一起傳入。與 main 函數(shù)不同的是,這個(gè)參數(shù)是一個(gè)字符串而不是一個(gè)字符串?dāng)?shù)組,如果程序參數(shù)有多個(gè),程序?qū)⒆孕薪馕鲞@個(gè)字符串。
Inst 是一個(gè) java.lang.instrument.Instrumentation 的實(shí)例,由 JVM 自動(dòng)傳入。java.lang.instrument.Instrumentation 是 instrument 包中定義的一個(gè)接口,也是這個(gè)包的核心部分,集中了其中幾乎所有的功能方法,例如類定義的轉(zhuǎn)換和操作等等。
2.jar文件打包
將這個(gè) Java 類打包成一個(gè) jar 文件,并在其中的 manifest 屬性當(dāng)中加入” Premain-Class”來(lái)指定步驟 1 當(dāng)中編寫(xiě)的那個(gè)帶有 premain 的 Java 類。(可能還需要指定其他屬性以開(kāi)啟更多功能),如下:
META_INF/MANIFEST.MF文件內(nèi)容:
Manifest-Version: 1.0 Premain-Class: Premain
3.運(yùn)行
用如下方式運(yùn)行帶有 Instrumentation 的 Java 程序:
java -javaagent:jar 文件的位置 [= 傳入 premain 的參數(shù) ]
虛擬機(jī)啟動(dòng)后的動(dòng)態(tài)instrument
通過(guò) java.lang.instrument.Instrumentation 和Attach API來(lái)實(shí)現(xiàn),Attach API在com.sun.tools.attach包里。
1.編寫(xiě)agentmain函數(shù)
public static void agentmain (String agentArgs, Instrumentation inst); [1] public static void agentmain (String agentArgs); [2]
同樣,[1] 的優(yōu)先級(jí)比 [2] 高,將會(huì)被優(yōu)先執(zhí)行。
2.打包
在.MF文件中增加Agent-Class屬性
Agent-Class: AgentMain
3.運(yùn)行
代碼截圖
Java應(yīng)用的監(jiān)控與診斷工具
- jconsole, jvisualvm, jprofiler 等
- MyPerf4J (https://github.com/LinShunKang/MyPerf4J)
- BTrace (https://github.com/btraceio/btrace)
- Arthas (https://github.com/alibaba/arthas)
- Bistoury (https://github.com/qunarcorp/bistoury)
參考
https://www.ibm.com/developerworks/cn/java/j-lo-jse61/






