java Agent

java Agent

1. 介绍

Java Agent 是从 JDK1.5 开始引入的,算是一个比较老的技术了。Java Agent 其实就是 java 命令的一个参数(即 -javaagent)

-javaagent 参数之后需要指定一个 jar 包,这个 jar 包需要同时满足下面两个条件:

在 META-INF 目录下的 MANIFEST.MF 文件中必须指定 premain-class 配置项。
premain-class 配置项指定的类必须提供了 premain() 方法。

public static void premain(String agentArgs, Instrumentation inst){

   ... 

}

在 Java 虚拟机启动时,执行 main() 函数之前,虚拟机会先找到 -javaagent 命令指定 jar 包,然后执行 premain-class 中的 premain() 方法。其实就是 main() 函数之前的一个拦截器。

2. 使用

创建java Agent 大致步骤

  1. 定义一个 MANIFEST.MF 文件,在其中添加 premain-class 配置项。

  2. 创建 premain-class 配置项指定的类,并在其中实现 premain() 方法,方法签名如下:

  3. 将 MANIFEST.MF 文件和 premain-class 指定的类一起打包成一个 jar 包。

  4. 使用 -javaagent 指定该 jar 包的路径即可执行其中的 premain() 方法。

eg:

premain() 方法有两个重载,如下所示,如果两个重载同时存在,一个参数的将会被忽略,两个参数的会被执行:

public class TestAgent {
    public static void premain(String agentArgs, 
            Instrumentation inst) {
        System.out.println("this is a java agent with two args");
        System.out.println("参数:" + agentArgs + "\n");
    }
    public static void premain(String agentArgs) {
        System.out.println("this is a java agent only one args");
        System.out.println("参数:" + agentArgs + "\n");
    }
}

源码如下:

# sun.instrument.InstrumentationImpl#loadClassAndStartAgent    
private void loadClassAndStartAgent(String var1, String var2, String var3) throws Throwable {
        ClassLoader var4 = ClassLoader.getSystemClassLoader();
        Class var5 = var4.loadClass(var1);
        Method var6 = null;
        NoSuchMethodException var7 = null;
        boolean var8 = false;

        try {
            var6 = var5.getDeclaredMethod(var2, String.class, Instrumentation.class);
            var8 = true;
        } catch (NoSuchMethodException var13) {
            var7 = var13;
        }

        if (var6 == null) {
            try {
                var6 = var5.getDeclaredMethod(var2, String.class);
            } catch (NoSuchMethodException var12) {
            }
        }

        if (var6 == null) {
            try {
                var6 = var5.getMethod(var2, String.class, Instrumentation.class);
                var8 = true;
            } catch (NoSuchMethodException var11) {
            }
        }

        if (var6 == null) {
            try {
                var6 = var5.getMethod(var2, String.class);
            } catch (NoSuchMethodException var10) {
                throw var7;
            }
        }

        setAccessible(var6, true);
        if (var8) {
            var6.invoke((Object)null, var3, this);
        } else {
            var6.invoke((Object)null, var3);
        }

        setAccessible(var6, false);
    }

创建 MANIFEST.MF 文件并打包,可以直接使用 maven-assembly-plugin 打包插件来完成这两项功能。在 pom.xml 中引入 maven-assembly-plugin 插件并添加相应的配置,如下所示:

<plugin>

    <groupId>org.apache.maven.plugins</groupId>

    <artifactId>maven-assembly-plugin</artifactId>

    <version>2.4</version>

    <configuration>

        <appendAssemblyId>false</appendAssemblyId>

        <!-- 将TestAgent的所有依赖包都打到jar包中-->

        <descriptorRefs>

            <descriptorRef>jar-with-dependencies</descriptorRef>

        </descriptorRefs>

        <archive>

            <!-- 添加MANIFEST.MF中的各项配置-->

            <manifest>

                <!-- 添加 mplementation-*和Specification-*配置项-->

                <addDefaultImplementationEntries>true

                </addDefaultImplementationEntries>

                <addDefaultSpecificationEntries>true

                </addDefaultSpecificationEntries>

            </manifest>

            <!-- 将 premain-class 配置项设置为com.xxx.TestAgent-->

            <manifestEntries>

                <Premain-Class>com.xxx.TestAgent</Premain-Class>

            </manifestEntries>

        </archive>

    </configuration>

    <executions>

        <execution>

            <!-- 绑定到package生命周期阶段上 -->

            <phase>package</phase>

            <goals>

                <!-- 绑定到package生命周期阶段上 -->

                <goal>single</goal>

            </goals>

        </execution>

    </executions>

</plugin>

打包

mvn package -Dcheckstyle.skip -DskipTests

在启动 TestMain 项目之前,需要在 VM options 中使用 -javaagent 命令指定前面创建的 test-agent.jar

  1. 参数:option1=value2,option2=value2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值