JPDA 架構研究2 - JVMTI代理

引入: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軟件打開查看內容:

wKiom1SFSz7xFsInAAJpNug-rho655.jpg

顯然,它是Oracle的Sun的JDK提供的Agent ,它提供了2個方法,一個是_Agent_OnLoad(),一個是_Agent_OnUnload()

wKiom1SFS37Ty0DhAAEzsbfIxTM606.jpg

和咱們設想的一致。





總結:

從上過程咱們彷佛能夠總結一些結論:

1. Agent 是在虛擬機啓動之時加載的,這個加載處於虛擬機初始化的早期.在這個時間點上:

  全部的 Java 類都未被初始化;全部的對象實例都未被建立; 於是,沒有任何 Java 代碼被執行; 

(從這點上說,最明顯的好處就是它能完成早期調試中用System.out.println()沒法解決的問題,由於System.out.println()前提是代碼行所在的類已經被初始化過了)

2.但在這個時候,咱們已經能夠:

操做 JVMTI 的 Capability 參數; 使用系統參數; 動態庫被加載以後,虛擬機會先尋找一個 Agent 入口函數.

相關文章
相關標籤/搜索