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