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

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