Ihre Anforderungen sind etwas unterspezifiziert. Unten finden Sie ein Beispielprogramm, das die Besucher-API von ASM zum Transformieren einer Klasse verwendet, von der angenommen wird, dass sie die Struktur Ihrer Frage in der resultierenden Klasse hat. Ich fügte eine Bequemlichkeitsmethode hinzu, die ein Bytearray und ein Bytearray zurücknimmt. Eine solche Methode kann in beiden Fällen verwendet werden, eine statische Transformation, die auf Klassendateien auf der Festplatte sowie in einem Instrumentation-Agenten angewendet wird.
Wenn ein ClassWriter
mit einem ClassVisitor
zu einem ClassReader
wie unten geführt kombiniert, wird es automatisch jedes Merkmal der Quellklasse replizieren, so dass Sie nur diese Methoden außer Kraft setzen müssen, wo Sie Änderungen anwenden möchten.
Hier visitMethod
ist außer Kraft gesetzt abzufangen, wenn die main
Verfahren zu begegnen, ihn zu ändern und visitEnd
ist außer Kraft gesetzt, die völlig neue Methode showTwo
anzuhängen. Die MainTransformer
wird RETURN
Anweisungen abfangen (es sollte nur eine in Ihrem Beispiel sein), um den Anruf an showTwo
davor einzufügen.
import org.objectweb.asm.*;
import org.objectweb.asm.commons.GeneratorAdapter;
public class MyTransformer extends ClassVisitor {
public static byte[] transform(byte[] b) {
final ClassReader classReader = new ClassReader(b);
final ClassWriter cw = new ClassWriter(classReader,
ClassWriter.COMPUTE_FRAMES|ClassWriter.COMPUTE_MAXS);
classReader.accept(new MyTransformer(cw), ClassReader.EXPAND_FRAMES);
return cw.toByteArray();
}
public MyTransformer(ClassVisitor cv) {
super(Opcodes.ASM5, cv);
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
MethodVisitor v=super.visitMethod(access, name, desc, signature, exceptions);
if(name.equals("main") && desc.equals("([Ljava/lang/String;)V"))
v=new MainTransformer(v, access, name, desc, signature, exceptions);
return v;
}
@Override
public void visitEnd() {
appendShowTwo();
super.visitEnd();
}
private void appendShowTwo() {
final MethodVisitor defVisitor = super.visitMethod(
Opcodes.ACC_PUBLIC, "showTwo", "()V", null, null);
defVisitor.visitCode();
defVisitor.visitFieldInsn(Opcodes.GETSTATIC,
"java/lang/System", "out", "Ljava/io/PrintStream;");
defVisitor.visitLdcInsn("Show Two Method");
defVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
"java/io/PrintStream", "println", "(Ljava/lang/String;)V", false);
defVisitor.visitInsn(Opcodes.RETURN);
defVisitor.visitMaxs(0, 0);
defVisitor.visitEnd();
}
class MainTransformer extends GeneratorAdapter
{
MainTransformer(MethodVisitor delegate, int access, String name, String desc,
String signature, String[] exceptions) {
super(Opcodes.ASM5, delegate, access, name, desc);
}
@Override
public void visitInsn(int opcode) {
if(opcode==Opcodes.RETURN) {
// before return insert c.showTwo();
super.visitVarInsn(Opcodes.ALOAD, 1); // variable c
super.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
"ClassName", "showTwo", "()V", false);
}
super.visitInsn(opcode);
}
}
}
@MartinFrank aber ich möchte ein neues Mwthod erstellen und es anrufen. der dort angegebene war auf einer grundlegenden Ebene! – Narayana
Nr. Passiert auch für mich. – icbytes