JavaAgent简介
- 关于JavaAgent的简介建议参考这篇博客,本文不做过多讲解。
方法
创建一个maven项目,pom文件如下(可以添加,下面是基本骨架):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.gloduck</groupId>
<artifactId>GAagent</artifactId>
<version>1.0</version>
<dependencies>
<!--javassist依赖-->
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.28.0-GA</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<!--打包插件,可以避免修改MANIFEST.MF-->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifestEntries>
<!--下面两个设置自定义的Agent,否则-javaagent启动时会报错-->
<Agent-Class>cn.gloduck.agent.CostAgent</Agent-Class>
<Premain-Class>cn.gloduck.agent.CostAgent</Premain-Class>
<Can-Redefine-Classes>true</Can-Redefine-Classes>
<Can-Retransform-Classes>true</Can-Retransform-Classes>
</manifestEntries>
</archive>
</configuration>
<executions>
<execution>
<!--设置打包时候执行插件-->
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>创建入口Class,具体参考文章。
1
2
3
4
5
6
7
8
9
10
11
12
13package cn.gloduck.agent;
import java.lang.instrument.Instrumentation;
public class CostAgent {
public static void premain(String agentArgs, Instrumentation inst) {
System.out.println("载入耗时统计Agent成功,参数为:" + agentArgs);
inst.addTransformer(new CostTransformer(agentArgs));
}
public static void premain(String agentArgs) {
}
}然后就是具体的一个类,使用javassist修改字节码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43package cn.gloduck.agent;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import java.io.ByteArrayInputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
public class CostTransformer implements ClassFileTransformer {
private String manageClassPath;
public CostTransformer(String manageClassPath) {
this.manageClassPath = manageClassPath;
}
@Override
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
if (!className.startsWith(manageClassPath)) {
return classfileBuffer;
}
CtClass cl = null;
try {
ClassPool pool = ClassPool.getDefault();
cl = pool.makeClass(new ByteArrayInputStream(classfileBuffer));
for (CtMethod declaredMethod : cl.getDeclaredMethods()) {
// 创建一个本地变量
declaredMethod.addLocalVariable("start", CtClass.longType);
declaredMethod.insertBefore("start = System.currentTimeMillis();");
String methodName = declaredMethod.getLongName();
declaredMethod.insertAfter("System.out.println(\"" + methodName + " 耗时为: \" + (System" +
".currentTimeMillis() - start));");
}
return cl.toBytecode();
} catch (Exception e) {
}
return classfileBuffer;
}
}然后使用
mvn package
进行打包。
使用
启动的时候在vm参数中添加:
1
-javaagent:<jarpath>[=<options>]
注意点
如果出现Could not find goal 'assembly' in plugin org.apache.maven.plugins:maven-assembly-plugin: among available goals help, single
则点击 Plugins - assembly - assembly:single