JVMTI開發教程之一個簡單的Agent

JVM TI是JDK提供的一套用於開發JVM監控, 問題定位與性能調優工具的通用編程接口(API)。
經過JVMTI,咱們能夠開發各式各樣的JVMTI Agent。這個Agent的表現形式是一個以c/c++語言編寫的動態共享庫。java

JVMTI Agent原理: Java啓動或運行時,動態加載一個外部基於JVM TI編寫的dynamic module到Java進程內,而後觸發JVM源生線程Attach Listener來執行這個dynamic module的回調函數。在函數體內,你能夠獲取各類各樣的VM級信息,註冊感興趣的VM事件,甚至控制VM的行爲。linux

JVMTI從功能上大體能夠分爲4類:

1. Heap
獲取全部類的信息,對象信息,對象引用關係,Full GC開始/結束,對象回收事件等。c++

2. 線程與堆棧
獲取全部線程的信息,線程組信息,控制線程(start,suspend,resume,interrupt…), Thread Monitor(Lock),獲得線程堆棧,控制出棧,方法強制返回,方法棧本地變量等。編程

3. Class & Object & Method & Field 元信息
class信息,符號表,方法表,redefine class(hotswap), retransform class,object信息,fields信息,method信息等。windows

4. 工具類
線程cpu消耗,classloader路徑修改,系統屬性獲取等。api

開發jvm ti agent,簡單的來說,就是開發一個c/c++的共享庫。在windows下後綴是dll,Linux/unix下是so,mac下就是dylib。因此咱們建立工程和編譯環境的時候,記得以共享庫(share library)的形式來構建。jvm

JVMTI的啓動方式

JVMTI有兩種啓動方式,第一種是隨java進程啓動時,自動載入共享庫,下文簡稱方式A。另外一種方式是,java運行時,經過attach api動態載入,下文簡稱方式B。函數

方式A的實現方式是經過在java啓動時傳遞一個特殊的option,例子以下:工具

java -agentlib:<agent-lib-name>=<options> Sample
注意,這裏的共享庫路徑是環境變量路徑,例如 java -agentlib:foo=opt1,opt2,java啓動時會從linux的LD_LIBRARY_PATH或windows的PATH環境變量定義的路徑處裝載foo.so或foo.dll,找不到則拋異常性能

java -agentpath:<path-to-agent>=<options> Sample
這是以絕對路徑的方式裝載共享庫,例如 java -agentpath:/home/admin/agentlib/foo.so=opt1,opt2

方式B的實現方式是經過attach api,這是一套純java的api,它負責動態地將dynamic module attach到指定進程id的java進程內並觸發回調。例子以下:

import java.io.IOException;
import com.sun.tools.attach.VirtualMachine;

public class VMAttacher {

    public static void main(String[] args) throws Exception {
	 // args[0]爲java進程id
         VirtualMachine virtualMachine = com.sun.tools.attach.VirtualMachine.attach(args[0]);
         // args[1]爲共享庫路徑,args[2]爲傳遞給agent的參數
         virtualMachine.loadAgentPath(args[1], args[2]);
         virtualMachine.detach();
    }

}

Attach API位於$JAVA_HOME/lib/tools.jar,因此在編譯時,須要將這個jar放入classpath。例如

javac -cp $JAVA_HOME/lib/tools.jar VMAttacher.java
相關文章
相關標籤/搜索