Created
March 12, 2024 11:10
-
-
Save lotabout/ede3577dec866d6fad7953612c2b4625 to your computer and use it in GitHub Desktop.
Java Agent example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package me.lotabout; | |
import com.sun.tools.attach.AgentInitializationException; | |
import com.sun.tools.attach.AgentLoadException; | |
import com.sun.tools.attach.AttachNotSupportedException; | |
import com.sun.tools.attach.VirtualMachine; | |
import java.io.IOException; | |
import java.lang.instrument.ClassFileTransformer; | |
import java.lang.instrument.Instrumentation; | |
import java.lang.instrument.UnmodifiableClassException; | |
import java.security.ProtectionDomain; | |
import org.objectweb.asm.ClassReader; | |
import org.objectweb.asm.ClassWriter; | |
import org.objectweb.asm.Opcodes; | |
import org.objectweb.asm.tree.ClassNode; | |
import org.objectweb.asm.tree.FieldInsnNode; | |
import org.objectweb.asm.tree.InsnList; | |
import org.objectweb.asm.tree.LdcInsnNode; | |
import org.objectweb.asm.tree.MethodInsnNode; | |
public class Launcher { | |
public static void main(String[] args) | |
throws IOException, AttachNotSupportedException, AgentLoadException, AgentInitializationException { | |
String pid = args[0]; | |
String path = Launcher.class.getProtectionDomain().getCodeSource().getLocation().getPath(); | |
VirtualMachine vm = VirtualMachine.attach(pid); | |
try { | |
vm.loadAgent(path); | |
} finally { | |
vm.detach(); | |
} | |
} | |
public static void premain(String agentArgs, Instrumentation inst) | |
throws UnmodifiableClassException { | |
inst.addTransformer(new MyTransformer(), true); | |
for (var clazz : inst.getAllLoadedClasses()) { | |
if (clazz.getName().startsWith("me.lotabout.Main")) { | |
inst.retransformClasses(clazz); | |
} | |
} | |
} | |
public static void agentmain(String agentArgs, Instrumentation inst) | |
throws UnmodifiableClassException { | |
premain(agentArgs, inst); | |
} | |
private static class MyTransformer implements ClassFileTransformer { | |
@Override | |
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, | |
ProtectionDomain protectionDomain, byte[] classfileBuffer) { | |
if (!className.startsWith("me/lotabout/Main")) { | |
return classfileBuffer; | |
} | |
System.out.println("transforming class: " + className); | |
ClassNode cn = new ClassNode(Opcodes.ASM4); | |
ClassReader cr = new ClassReader(classfileBuffer); | |
cr.accept(cn, 0); | |
for (var method : cn.methods) { | |
System.out.println("patching Method: " + method.name); | |
var list = new InsnList(); | |
list.add(new FieldInsnNode(Opcodes.GETSTATIC, "java/lang/System", "out", | |
"Ljava/io/PrintStream;")); | |
list.add(new LdcInsnNode(">> calling Method: " + method.name)); | |
list.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", | |
"(Ljava/lang/String;)V", false)); | |
method.instructions.insert(list); | |
} | |
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); | |
cn.accept(cw); | |
return cw.toByteArray(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Main-Class: me.lotabout.Launcher | |
Premain-Class: me.lotabout.Launcher | |
Agent-Class: me.lotabout.Launcher | |
Can-Redefine-Classes: true | |
Can-Retransform-Classes: true | |
Can-Set-Native-Method-Prefix: true |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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>me.lotabout</groupId> | |
<artifactId>my-agent</artifactId> | |
<version>1.0-SNAPSHOT</version> | |
<properties> | |
<maven.compiler.source>11</maven.compiler.source> | |
<maven.compiler.target>11</maven.compiler.target> | |
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | |
</properties> | |
<dependencies> | |
<dependency> | |
<groupId>org.ow2.asm</groupId> | |
<artifactId>asm</artifactId> | |
<version>9.4</version> | |
</dependency> | |
<dependency> | |
<groupId>org.ow2.asm</groupId> | |
<artifactId>asm-tree</artifactId> | |
<version>9.4</version> | |
</dependency> | |
</dependencies> | |
<build> | |
<plugins> | |
<plugin> | |
<groupId>org.apache.maven.plugins</groupId> | |
<artifactId>maven-assembly-plugin</artifactId> | |
<version>3.6.0</version> | |
<configuration> | |
<descriptorRefs> | |
<descriptorRef>jar-with-dependencies</descriptorRef> | |
</descriptorRefs> | |
<archive> | |
<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile> | |
</archive> | |
</configuration> | |
<executions> | |
<execution> | |
<phase>package</phase> | |
<goals> | |
<goal>single</goal> | |
</goals> | |
</execution> | |
</executions> | |
</plugin> | |
</plugins> | |
</build> | |
</project> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment