Le vostre esigenze sono un po 'sottostimate. Di seguito è riportato un programma di esempio che utilizza l'API visitatore di ASM per trasformare una classe che si presuppone abbia la struttura della domanda nella classe risultante. Ho aggiunto un metodo comodo prendendo un array di byte e restituendo un array di byte. Tale metodo può essere utilizzato in entrambi i casi, una trasformazione statica applicata ai file di classe su disco e in un agente di Strumentazione.
Quando si combinano un ClassWriter
con un ClassVisitor
passato a una ClassReader
come sotto, si replicherà automaticamente tutte le funzionalità del classe di origine in modo da avere eseguire l'override solo questi metodi in cui si desidera applicare le modifiche.
Qui, visitMethod
è sovrascritto per intercettare quando incontrano il metodo main
per modificarla e visitEnd
è sovrascritto per aggiungere il tutto nuovo metodo showTwo
. Lo MainTransformer
intercetterà le istruzioni RETURN
(dovrebbe essercene solo una nel tuo esempio) per inserire la chiamata a showTwo
prima di essa.
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 ma voglio creare un nuovo Mwthod e chiamarlo. quello specificato c'era al livello base! – Narayana
Np. Succede anche per me. – icbytes