如何在Java上重新定义已定义的类

我希望在下面的代码中调用newTarget.a()和newTarget.b()时应用调制的ASM类,使它看起来像这样

当我使用Modified ASM Class调用newTarget.a()和newTarget.b()时,如何获得以下结果?

码:

package asm; 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; import static org.objectweb.asm.Opcodes.ASM5; public class Main { public static void main(String[] args) throws Exception { Target target = new Target(); target.a(); target.b(); ClassReader reader = new ClassReader("asm.Main$Target"); ClassWriter writer = new ClassWriter(0); ClassVisitor visitor = new TestClassVisitor(ASM5, writer); reader.accept(visitor, 0); byte[] transformed = writer.toByteArray(); // Apply byte[] transformed Target newTarget = new Target(); newTarget.a(); newTarget.b(); } static class Target { private void a() { System.out.println("first method"); } private void b() { System.out.println("second method"); } } static class TestClassVisitor extends ClassVisitor { public TestClassVisitor(int i, ClassVisitor classVisitor) { super(i, classVisitor); } @Override public MethodVisitor visitMethod(int i, String s, String s1, String s2, String[] strings) { MethodVisitor visitor = super.visitMethod(i, s, s1, s2, strings); if (!s.equals("")) { return visitor; } return new TestMethodVisitor(api, visitor); } } static class TestMethodVisitor extends MethodVisitor { public TestMethodVisitor(int i, MethodVisitor methodVisitor) { super(i, methodVisitor); } @Override public void visitCode() { super.visitCode(); super.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;"); super.visitLdcInsn("transformed method"); super.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V", false); } @Override public void visitEnd() { super.visitEnd(); } } } 

想要结果:

第一种方法

第二种方法

转化方法

第一种方法

转化方法

第二种方法

您正在寻找Java Instrumentation API 。 它要求您通过-javaagent参数附加Java代理。 使用API​​,您可以调用:

 instrumentation.redefineClasses( new ClassDefinition(asm.Main.Target.class, classWriter.toBytes()) ); 

确保不更改类的布局,大多数JVM目前不支持此类。