java探针利用了javaAgent + ASM字节码注入工具实现了动态修改类文件的功能。这是很多arthas和APM应用监控系统如Skywalking的基础。
首先什么是JavaAgent呢?
什么是javaAgent?
JavaAgent 是JDK 1.5 以后引入的,也可以叫做Java代理。是一种可以动态修改 Java 字节码的技术。Java 类编译之后形成字节码被 JVM 执行,在 JVM 在执行这些字节码之前获取这些字节码信息,并且通过字节码转换器对这些字节码进行修改,来完成一些额外的功能。
从用户使用层面来看,Java Agent 一般通过在应用启动参数中添加 -javaagent 参数添加 ClassFileTransformer 字节码转换器。 在 Java 虚拟机启动时,执 行main() 函数之前,Java 虚拟机会先找到 -javaagent 命令指定 jar 包,然后执行 premain-class 中的 premain() 方法。用一句概括其功能的话就是:main() 函数之前的一个拦截器
agent的代码与你的main方法在同一个JVM中运行;被同一个system classloader装载;被同一的安全策略 (security policy) 和上下文 (context) 所管理。
javaAgent可以实现的功能
1.javaAgent能够在执行java字节码生成Class对象之前进行拦截并对字节码进行修改
2.在jvm运行期间修改已经加载的字节码
通过以上两种就可以实现在一些框架或是技术的采集点进行字节码修改,可以对应用进行监控,或是对执行指定方法或是接口时额外添加操作(打印日志、打印方法执行时间、采集方法的入参和结果等)
使用入门:
- 编写一个maven项目,创建一个带有下列方法的java类。注意方法签名保持一致,参数Instrumentation inst也可省略。
public class MyAgent {
public static void premain(String agentOps, Instrumentation inst) {
System.out.println("Hello Main Method, I'm premain Method from agent, agentOps:" + agentOps);
}
}
- pom文件里添加下面的插件
<build>
<plugins>
<plugin>
<!--引入maven-jar-plugin-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifestEntries>
<!--这里添加premain方法的类全路径,maven会你生成manifest文件-->
<premain-class>com.jun.sail.agent.MyAgent</premain-class>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
</configuration>
</plugin>
</plugins>
</build>
-
然后
mvn clean package
打包即可。看下打好的jar包,可以看到META-INF文件夹有个MANIFEST.MF文件,就是刚才插件的功劳。 -
最后找个项目(jar包启动的项目,如springboot项目),启动时添加jvm参数
-javaagent:E:\code\my-java-agent\target\my-java-agent-1.0-SNAPSHOT.jar
指到刚才打好的代理jar包。可以跟参数,对应着premain方法里的agentOps参数
即可在控制台看到先打印了
Hello Main Method, I'm premain Method from agent, agentOps:123
,然后才执行了main方法。
另外,其实IDE的debug模式启动时也是添加了javaAgent代理
从这里也可以看出Javaagent可以指定多个
上面只是简单介绍了JavaAgent的使用,那怎么去修改加载的类文件呢,这就涉及到了Instrumentation接口,这个才是agent实现更强大功能的核心所在!