java agent簡介

wang03發表於2021-09-05

java agent簡介

  1. 主要就是兩種,一種的方法是premain,一種是agentmain。這兩種的區別是:

    1. premain是在jvm啟動的時候類載入到虛擬機器之前執行的
    2. agentmain是可以在jvm啟動後類已經載入到jvm中了,才去轉換類。這種方式會轉換會有一些限制,比如不能增加或移除欄位。
  2. 具體的做法,兩者的實際做法是差不多的:

    1. premain

      定義個靜態方法 public static void premain(String args, Instrumentation inst),

    在生成jar包中MANIFEST.MF檔案中需要有Premain-Class: xxx.xxx ,xxx.xxx就是上面premain方法所在的類名

    在java 的啟動引數中新增 -javaagent:/jar包路徑[=agentArgs]

    這樣定義了後jvm啟動時,就會去載入javaagent中指定的jar包,查詢MANIFEST.MF檔案中Premain-Class屬性的類,執行premain方法。

    參考asm文件簡單修改了下列印方法執行時間的demo

    blogdemo/javabasedemo/agentdemo at main · wbo112/blogdemo (github.com)

    1. agentmain

      定義個靜態方法public static void agentmain(String agentOps, Instrumentation instrumentation),

      在生成jar包中MANIFEST.MF檔案中需要有Agent-Class: xxx.xxx (xxx.xxx就是上面agentmain方法所在的類名)
      Can-Retransform-Classes: true

      使用下面程式碼,將agent新增到指定java程式

       		vm = VirtualMachine.attach(pid);
              try {
                  vm.loadAgent("D:\\tmp\\my-java-agent-1.0-jar-with-dependencies.jar", null);
              } finally {
                  vm.detach();
              }
      

      這個github找到一個很不錯的案例。wujiuye/bytecode-book: 《Java虛擬機器位元組碼從入門到實戰》一書的配套程式碼 (github.com)

  3. 具體類的轉換處理一般都是用asm之類修改位元組碼的開源元件。主要就是實現ClassFileTransformer介面,對入參的byte[]這個就是class類的位元組陣列了,對這個進行轉換,返回新的class類的byte[]位元組陣列

相關文章