常见的Java Agent有如下几种:
- ByteBuddy:基于Java字节码增强库,可以实现类加载的字节码增强。
- ASM:一个轻量级Java字节码操作库,ASM可以动态生成类、方法或 Field,或者对现有类进行操作。
- Javassist:Java字节码操作库,它可以在字节码层面上修改Java程序。
- Instrument:Java的一个API,可以在运行时修改字节码,Instrument的优点在于它对运行时的影响较小。
使用ByteBuddy作为Java Agent的示例
-
通过Maven引入ByteBuddy,会自动把ByteBuddy转换成Java Agent。
xml
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
<version>1.8.17</version>
<scope>runtime</scope>
</dependency> -
实现java.lang.instrument.Instrumentation的premain方法,在其中使用ByteBuddy的API增强字节码,下面是一个例子。
```java
import java.lang.instrument.Instrumentation;
import net.bytebuddy.agent.builder.AgentBuilder;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.utility.JavaModule;public class ExampleAgent {
public static void premain(String arguments, Instrumentation instrumentation) { new AgentBuilder.Default() .type((TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) -> typeDescription.getName().equals("java.util.ArrayList")) .transform((DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module) -> builder.method(named("add")) .intercept(MethodDelegation.to(MyPrepender.class)) .make()) .installOn(instrumentation); }
}
public class MyPrepender {
public static void add(@SuperCall Callable<List<String>> zuper, @Origin Method method, @AllArguments Object[] args) throws Exception { System.out.println("Before " + method.getName() + ": " + Arrays.toString(args)); zuper.call(); System.out.println("After " + method.getName() + ": " + Arrays.toString(args)); }
}
```
使用ASM作为Java Agent的示例
-
通过Maven引入ASM库。
xml
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<version>9.0</version>
</dependency> -
实现java.lang.instrument.Instrumentation的premain方法,在其中使用ASM进行字节码增强,下面是一个例子。
```java
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;public class ExampleAgent {
public static void premain(String arguments, Instrumentation instrumentation) { instrumentation.addTransformer((ClassLoader classLoader, String s, Class<?> aClass, ProtectionDomain protectionDomain, byte[] bytes) -> { ClassReader reader = new ClassReader(bytes); ClassWriter writer = new ClassWriter(reader, 0); ClassVisitor visitor = new ClassVisitor(Opcodes.ASM9, writer) { @Override public MethodVisitor visitMethod(int i, String s, String s1, String s2, String[] strings) { MethodVisitor mv = super.visitMethod(i, s, s1, s2, strings); return new MethodVisitor(Opcodes.ASM9, mv) { @Override public void visitInsn(int opcode) { if (opcode == Opcodes.RETURN) { super.visitLdcInsn("ASMExample message"); super.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/System", "out", "(Ljava/lang/Object;)V", false); } super.visitInsn(opcode); } }; } }; reader.accept(visitor, 0); return writer.toByteArray(); }); }
}
```
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:常见的Java Agent有哪些? - Python技术站