APM(1)静态javaagent使用

javaagent是java5的新特性,依赖他我们可以构建一个独立于应用程序的代理程序(Agent),用来监测和协助运行在 JVM 上的程序,甚至能够替换和修改某些类的定义,过程上简单来说就是编写一个特殊的类将其打成jar包,要监控(拦截)的项目在启动时jvm参数加上特殊的启动命令,即可监控该项目

javaagent使用步骤

  1. 任意编写一个类,类中有如下两个方法之一即可

    1
    2
    3
    4
    5
    6
    /**
    * @param arg agentArgs 是 premain 函数得到的程序参数,随同 “– javaagent”一起传入。
    * @param instrumentation instrumentation 是一个 java.lang.instrument.Instrumentation 的实例,由 JVM 自动传入
    */
    public static void premain(String arg, Instrumentation instrumentation){}
    public static void premain(String arg){}

    示例代码:

    1
    2
    3
    4
    5
    6
    7
    8
    package com.agenttest;
    import java.lang.instrument.Instrumentation;
    public class FirstAgent {
    //静态装载agent
    public static void premain(String arg, Instrumentation instrumentation){
    System.out.println("这里执行了premain()方法,进行了装载");
    }
    }
  2. 在pom文件中加入如下配置,让该类在打包成jar包时他的MANIFEST.MF文件中有代表该类为Agent类的信息

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <build>
    <plugins>
    <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.2</version>
    <configuration>
    <archive>
    <manifestEntries>
    <Project-name>${project.name}</Project-name>
    <Project-version>${project.version}</Project-version>
    <Premain-Class>com.agenttest.FirstAgent</Premain-Class>
    <!-- <Boot-Class-Path>javassist-3.18.1-GA.jar</Boot-Class-Path>
    <Agent-Class>com.agenttest.DynamicAgent</Agent-Class>
    <Can-Redefine-Classes>true</Can-Redefine-Classes>-->
    </manifestEntries>
    </archive>
    <skip>true</skip>
    </configuration>
    </plugin>
    </plugins>
    </build>

    标签下加上Agent类的全路径,完成后将该类所在的项目打成jar包
    参数含义:

    1
    2
    3
    4
    5
    6
    7
    8
    #动态agent 类
    Agent-Class: com.agenttest.DynamicAgent
    #agent 依懒包逗号分割
    Boot-Class-Path: javassist-3.18.1-GA.jar
    #是否允许重复装载
    Can-Redefine-Classes: true
    #静agent 类
    Premain-Class: com.agenttest.FirstAgent
  3. 在运行要被”拦截”的项目时,添加一个jvm的启动参数
    -javaagent:xxx.jar(=parama=aaa):xxx是jar包的路径,后面可以接着跟参数
    mark测试类中示例代码:

    1
    2
    3
    4
    5
    public class FirstAgentTest {
    public static void main(String[] args) {
    System.out.println("main方法中的输出");
    }
    }
  4. 运行结果
    会先执行premain中的方法,在执行main方法

    1
    2
    这里执行了premain()方法,进行了装载
    main方法中的输出

javaagent的jar和普通jar区别

mark

javaagent 底层流程

javaagent 装载时序图(premain):

mark

Class 装载时序图

mark


-------------本文结束感谢您的阅读-------------