最近在学习Java Agent,说一下学习的一些心得。
JavaAgent一种在加载类的时候,对字节码进行修改的技术,中文含义Java探针技术。
其原理:
JavaAgent是jdk1.5以后引入的技术,是一种在JVM加载class二进制文件的时候,利用ASM动态的修改加载的class文件的JAVA代理技术。
创建agent
上代码: 第一步:创建一个class类,创建两个方法
import java.lang.instrument.Instrumentation;
/**
* @author fade
* @Title: MyAgent
* @ProjectName my-agent
* @Description: TODO
* @date 2021/4/123:51 下午
*/
public class MyAgent {
/**
* 该方法在main方法之前运行,与main方法运行在同一个JVM中
* 并被同一个System ClassLoader装载
* 被统一的安全策略(security policy)和上下文(context)管理
*
* @param agentOps
* @param inst
* @author fade
* @create 2021/4/123:51 下午
*/
public static void premain(String agentOps, Instrumentation inst) {
System.out.println("=========premain方法执行========");
System.out.println(agentOps);
}
/**
* 如果不存在 premain(String agentOps, Instrumentation inst)
* 则会执行 premain(String agentOps)
*
* @param agentOps
* @author fade
* @create 2021/4/123:51 下午
*/
public static void premain(String agentOps) {
System.out.println("=========premain方法执行2========");
System.out.println(agentOps);
}
}
public static void agentmain(String args, Instrumentation inst)
或 public static void agentmain(String args)
方法。并且在二者同时存在时以前者优先。args和inst与premain中的一致。
第二步: 第一种方式(maven方式) pom文件中添加:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Premain-Class>com.sage.agent.MyAgent</Premain-Class>
<Agent-Class>com.sage.agent.MyAgent</Agent-Class>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
</manifestEntries>
</archive>
</configuration>
</plugin>
Premain-Class 、Agent-Class指向agent的主类,即刚才创建的MyAgent。
第二种方式(配置文件方式) 在resource中创建并设置MANNIFEST.MF,指定Agent-Class:
Manifest-Version: 1.0
Agent-Class: com.sage.agent.MyAgent
Created-By: 1.6.0_29
一个简单的agent就实现了
如何加载 Java Agent
通过JVM参数 -javaagent:**.jar 启动,程序启动的时候,会优先加载Java Agent,并执行其 premain 方法,这个时候,其实大部分的类都还没有被加载,这个时候可以实现对新加载的类进行字节码修改,但是如果 premain 方法执行失败或抛出异常,那么JVM会被中止,这是很致命的问题。