【Agent】Java Agent 介绍与使用

邓敏 2021年12月18日 104次浏览

什么是Java Agent

Java Agent是在Java 1.5版本之才有的东西,他可以构建一个独立Java服务外的一个代理程序,也就是Agent。通常会用它来做一下Java服务的监控,或者替换其他JVM上的程序,还可以实现虚拟机上的AOP功能。

Agent分为两种,一种是程序启动前触发的,一种是程序启动后触发的。

编写Agent

接下来我们来看看如何使用
首先我们创建一个Maven项目,同时在项目中编写好这个类。

public class TestAgent {
    public static void agentmain(String agentArgs,
                               Instrumentation inst)throws Exception {
        // 注册一个 Transformer,该 Transformer在类加载时被调用
        inst.addTransformer(new com.xxx.Transformer(), true);
        inst.retransformClasses(TestClass.class);
        System.out.println("premain done");
    }

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

如果agentmain存在重载的方法,将会忽略第二个方法,而执行第第一个带有Instrumentation方法。

通过maven将Agent打包

在pom文件中添加

<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><!-- 添加MANIFEST.MF中的各项配置-->
                            <!-- 添加 mplementation-*和Specification-*配置项-->
                            <addDefaultImplementationEntries>true
                            </addDefaultImplementationEntries>
                            <addDefaultSpecificationEntries>true
                            </addDefaultSpecificationEntries>
                        </manifest>
                        <!-- 将 premain-class 配置项设置为com.xxx.TestAgent-->
                        <manifestEntries>
                            <Can-Retransform-Classes>true</Can-Retransform-Classes>
                            <Agent-Class>com.xxx.TestAgent</Agent-Class>
                        </manifestEntries>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <!-- 绑定到package生命周期阶段上 -->
                        <phase>package</phase>
                        <goals>
                            <!-- 绑定到package生命周期阶段上 -->
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
</plugin>

然后执行打包命令

mvn package -Dcheckstyle.skip -DskipTests

使用agent包

打完包后会发现目录下会多一个target包

image.png

保存好teat-agent.jar的路径

新建一个main方法启动类

public class Main {
    public static void main(String[] args) {
        System.out.println(new TestClass().getNumber());
    }
}

在启动Main方法之前,配置好启动的参数

-javaagent:/Users/***/teat-agent.jar

启动之后就会发现,在Main方法之前他会先执行Agent包中编写好的agentmain方法内的东西。这样我们就达到了使用Agent的目的。