引入:java
咱們先從JVMTI講起。JVMTI的主要做用是提供一組接口來檢測VM的狀態和控制VM中運行的JAVA程序。JVMTI是個雙向接口:jvm
JVMTI的客戶端叫Agent,它會在VM發生變化時經過事件機制被通知到變化。ide
JVMTI的服務端是許多函數,它們會和VM實際打交道並把結果告知Agent.
函數
實踐:spa
咱們這裏先來看下Agent.
3d
Agent的方法定義在哪裏呢?它們定義在$JAVA_HOME/include/jvmti.h文件中。代理
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved); JNIEXPORT void JNICAL。 Agent_OnUnload(JavaVM *vm);
Agent_OnLoad方法:
指針
當代理被VM加載時,會由VM調用Agent_Onload方法。此時VM有以下能力:調試
(1)VM的System Property已經被設置完畢。對象
(2)VM的Capabilities已經被設置完畢。
(3)任何字節碼都沒被執行。
(4)任何類都沒有被加載。
(5)任何對象都沒有被建立。
Agent_OnLoad實現過程當中,最重要的事情之一就是調用GetEnv方法來獲取JVMTI環境的指針。
jint GetEnv(JavaVM *vm, void **env, jint version);
這樣,這個代理就能夠知道被代理的環境的所有信息。
Agent_OnUnload方法:
當代理被VM卸載時,會由VM調用Agent_OnUnload方法。通常發生在終止VM的時候,它通常能夠用來清理在Agent_OnLoad階段建立的資源。
由於咱們在遠程調試時候啓動JVM時候加了代理參數:
java -agentlib:<agentLibName> ,而agentLibName咱們配置的是jdwp, 因此它就對應上jdwp.dll.
也就是遠程調試時候自動會在啓動target VM時候啓用jdwp這個代理庫.
當明白了代理的做用後,咱們來找其的實現。在Sun的JDK中,咱們找到了jdwp.dll (Linux環境則是jdwp.so) . 它位於 $JAVA_HOME/jre/bin目錄下。咱們用exeScope軟件打開查看內容:
顯然,它是Oracle的Sun的JDK提供的Agent ,它提供了2個方法,一個是_Agent_OnLoad(),一個是_Agent_OnUnload()
和咱們設想的一致。
總結:
從上過程咱們彷佛能夠總結一些結論:
1. Agent 是在虛擬機啓動之時加載的,這個加載處於虛擬機初始化的早期.在這個時間點上:
全部的 Java 類都未被初始化;全部的對象實例都未被建立; 於是,沒有任何 Java 代碼被執行;
(從這點上說,最明顯的好處就是它能完成早期調試中用System.out.println()沒法解決的問題,由於System.out.println()前提是代碼行所在的類已經被初始化過了)
2.但在這個時候,咱們已經能夠:
操做 JVMTI 的 Capability 參數; 使用系統參數; 動態庫被加載以後,虛擬機會先尋找一個 Agent 入口函數.