Skip to content

Instantly share code, notes, and snippets.

@lotabout
Created March 12, 2024 11:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lotabout/ede3577dec866d6fad7953612c2b4625 to your computer and use it in GitHub Desktop.
Save lotabout/ede3577dec866d6fad7953612c2b4625 to your computer and use it in GitHub Desktop.
Java Agent example
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();
}
}
}
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
<?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