java之java agent
示例作用
向已存在的方法中添加其它指令
新建项目
配置文件指定premainclass
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>com.kevin.agent.Application</Main-Class>
<Premain-Class>com.kevin.agent.MyAgent</Premain-Class>
</manifestEntries>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
添加asm依赖
<dependencies>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>7.3</version>
</dependency>
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-tree</artifactId>
<version>7.3</version>
</dependency>
</dependencies>
MyAgent
新增class com.kevin.agent.MyAgent
public class MyAgent {
public static void premain(String agentArgs, Instrumentation inst) {
System.out.println("premain");
inst.addTransformer(new MyTransformer());
System.out.println("premain end");
}
static class MyTransformer implements ClassFileTransformer, Opcodes {
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer) throws
IllegalClassFormatException {
if (className.startsWith("java") ||
className.startsWith("javax") ||
className.startsWith("jdk") ||
className.startsWith("sun") ||
className.startsWith("com/sun") ||
className.startsWith("org/example")) {
// Skip JDK classes and profiler classes
return null;
}
ClassReader cr = new ClassReader(classfileBuffer);
ClassNode classNode = new ClassNode(ASM7);
cr.accept(classNode, ClassReader.SKIP_FRAMES);
for (MethodNode methodNode : classNode.methods) {
for (AbstractInsnNode node : methodNode.instructions.toArray()) {
System.out.println(node.getOpcode());
if (node.getOpcode() == INVOKEVIRTUAL) {
InsnList instrumentation = new InsnList();
instrumentation.add(new FieldInsnNode(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"));
instrumentation.add(new LdcInsnNode("Hello, Instrumentation!"));
instrumentation
.add(new MethodInsnNode(INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false));
methodNode.instructions.insert(node, instrumentation);
}
}
}
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
classNode.accept(cw);
return cw.toByteArray();
}
}
}
启动类
public class Application {
public static void main(String []args){
System.out.println("Start main");
System.out.println("Stop main");
}
}
启动命令
java -javaagent:target/jvm-agent-1.0-SNAPSHOT.jar -jar target/jvm-agent-1.0-SNAPSHOT.jar