jvm-sanbox詳解-agent方式和attach方式

Instrumentation包的簡介

JDK從1.5開始,在rt.jar包下有了java.lang.instrument這個文件夾,剛開始只支持agent方式啓動,但使用還是不太方便,因爲我們在JDK1.6後增加了attach方式。在官方文檔提供了兩種方式

agent命令方式

在jvm啓動參數中增加
-javaagent:jarpath[=options]
agent有兩點要求:

  1. agent jar必須包含Premain-Class屬性,值是agent class啓動類
  2. 必須實現 一個 public static premain的方法
  3. JDK加載這個方法使用系統類加載器( ClassLoader.getSystemClassLoader),這個premain方法在同樣的security和 classloader 規則下,也就是說應用程序能做的事情,這裏都可以做,如創建線程等(這裏意味着agent與運行程序共享同一個jvm)。
public static void premain(String agentArgs, Instrumentation inst);
public static void premain(String agentArgs);

這裏注意JVM默認會先調用上面那個參數全的方法,沒有實現該方法纔會調用下面那個簡略版方法

運行過程中attach方式

  1. agent JAR必須包含Agent-Class屬性,值是agent class的啓動類。
  2. 必須實現 public static agentmain 方法
  3. 系統類加載器(ClassLoader.getSystemClassLoader)必須支持加載agent jar到系統class路徑下(可以設置參數關閉)
public static void agentmain(String agentArgs, Instrumentation inst);
public static void agentmain(String agentArgs);

同上面agent方式,也會優先調用參數全的那個方法

- agent jar支持的屬性有

  1. Premain-Class :agent命令啓動參數,類須實現premain方法
  2. Agent-Class :jvm啓動後加載,類需實現agentmain方法
  3. Boot-Class-Path:啓動類加載器加載的路徑
  4. Can-Redefine-Classes:是否可以重新定義類,默認false
  5. Can-Retransform-Classes:是否可以變形類,默認false
  6. Can-Set-Native-Method-Prefix:是否設置內部方法前綴,默認false

agent打包插件

上面agent的這些屬性,我們在打包時候如何設置呢,這裏以maven-assembly-plugin插件爲例,我們在assembly插件官網看到使用說明(http://maven.apache.org/plugins/maven-assembly-plugin/usage.html)
可以使用archive屬性指定

<project>
  [...]
  <build>
    [...]
    <plugins>
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>3.3.0</version>
        <configuration>
          [...]
          <archive>
            <manifest>
              <mainClass>org.sample.App</mainClass>
            </manifest>
          </archive>
        </configuration>
        [...]
      </plugin>
      [...]
</project>

這樣打包後,我們在META-INF/MANIFEST.MF文件中寫入值

[...]
Main-Class: org.sample.App

如果自己編寫的模塊如jvm-sanbox既支持agent方式又要支持attach方式,那麼我們可以這麼來寫

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <executions>
        <execution>
            <goals>
                <goal>attached</goal>
            </goals>
            <phase>package</phase>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
                <archive>
                    <manifestEntries>
                        <Premain-Class>com.xxxx</Premain-Class>
                        <Agent-Class>com.xxx</Agent-Class>
                        <Can-Redefine-Classes>true</Can-Redefine-Classes>
                        <Can-Retransform-Classes>true</Can-Retransform-Classes>
                    </manifestEntries>
                </archive>
            </configuration>
        </execution>
    </executions>
</plugin>

參考文檔:
官方文檔:https://docs.oracle.com/javase/8/docs/api/index.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章