编写Java Agent插件
编写Java Agent插件
我们通过使用Instrumentation编写一个Java Agent程序,实现业务代码插桩,在方法执行之前插入埋点,以及在方法执行异常或者执行完成之前插入埋点,用于收集方法执行日记信息。Java Agent本质上是一个插件。
新建一个项目,项目构建工具使用maven,项目名为my-java-agent。创建一个类并编写premain方法,如代码清单7-1所示。
代码清单7-1 MyJavaAgent的premain方法
public class MyJavaAgent { public static void premain(String agentOps, Instrumentation instrumentation) { System.out.println("premain function run..."); } }
修改maven依赖配置文件,配置项目打包所需的插件,代码如下:
<build> <plugins> <plugin> <artifactId>maven-assembly-plugin</artifactId> <configuration> <!-- 把依赖的jar包一起打包 --> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <!-- 注册premain的class --> <manifestEntries> <Premain-Class>com.wujiuye.agent.MyJavaAgent</Premain-Class> </manifestEntries> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
其中Premain-Class标签用于配置MANIFEST.MF文件的Premain-Class参数。打包后将jar包解压,可在META-INF目录下看到MANIFEST.MF文件,文件内容如下:
Manifest-Version: 1.0 Archiver-Version: Plexus Archiver Created-By: Apache Maven Built-By: wjy Build-Jdk: 1.8.0_144 Premain-Class: com.wujiuye.agent.MyJavaAgent
另外新建一个demo项目,在main方法中调用业务类的方法。如代码清单7-2所示。
代码清单7-2 demo项目代码
public class UserService { public Map<String, Object> queryUser(String username, Integer age) { Map<String, Object> result = new HashMap<>(); result.put("username", username); result.put("age", age); return result; } } public class DemoAppcliction { public static void main(String[] args) { System.out.println("main function runing..."); Map<String, Object> user = new UserService() .queryUser("wujiuye", 25); System.out.println(user); } }
如果想要将my-java-agent插件附着在demo项目运行,可在使用java命令启动demo项目时配置-javaagent参数,或者在IDEA中配置VM options加上-javaagent参数。以在IDEA中配置VM options为例,如图7.1所示:

图7.1 demo项目启动VM参数配置
demo项目运行输出如下:
premain function run... main function runing... {age=25, username=wujiuye}
可见,我们所编写的my-java-agent程序的premain方法先于demo项目的main方法执行了。
premain方法的两个参数:
◆agentOps:用于接收我们在配置javaagent参数时附加的信息,例如:
-javaagent:my-java-agent-1.0-jar-with-dependencies.jar=com.wujiuye
则premain方法中接收到agentOps参数的值为“com.wujiuye”。
◆instrumentation:Instrumentation实例,由JVM传递。