I am trying to change the code content of catch block of existing try/catch block inside a method.
public static void hello(Throwable throwable) {
    try{
        System.out.println("in try");
    }catch(Exception e){
        System.out.println("in catch");
    }
}
My intention is to add a method call inside catch block. Something like,
public static void hello(Throwable throwable) {
    try{
        System.out.println("in Try");
    }catch(Exception e){
        *passException(e);*
        System.out.println("in catch");
    }
}
Note: I have already tried to override visitTryCatchBlock method of MethodVisitor. And experimented with visiting the label in many ways but nothing helped. I can't find this in any of the documentation/guide/examples on the net. I hope I have explained clearly that I am posting this question after trying everything. 
It’s not clear what actual obstacle you are facing as your description of your attempts points into the right direction, visitTryCatchBlock and visitLabel. Here is a self contained example which does the job:
import java.io.IOException;
import java.lang.reflect.Method;
import org.objectweb.asm.*;
public class EnhanceExceptionHandler {
    static class Victim {
        public static void hello(boolean doThrow) {
            try {
                System.out.println("in try");
                if(doThrow) {
                    throw new Exception("just for demonstration");
                }
            } catch(Exception e){
                System.out.println("in catch");
            }
        }
        static void passException(Exception e) {
            System.out.println("passException(): "+e);
        }
    }
    public static void main(String[] args)
        throws IOException, ReflectiveOperationException {
        Class<EnhanceExceptionHandler> outer = EnhanceExceptionHandler.class;
        ClassReader classReader=new ClassReader(
            outer.getResourceAsStream("EnhanceExceptionHandler$Victim.class"));
        ClassWriter classWriter=new ClassWriter(classReader,ClassWriter.COMPUTE_FRAMES);
        classReader.accept(new ClassVisitor(Opcodes.ASM5, classWriter) {
            private String className;
            @Override
            public void visit(int version, int access, String name, String signature,
                String superName, String[] interfaces) {
                className=name;
                super.visit(version, access, name, signature, superName, interfaces);
            }
            @Override
            public MethodVisitor visitMethod(int access, String name, String desc,
                String signature, String[] exceptions) {
                MethodVisitor visitor
                    = super.visitMethod(access, name, desc, signature, exceptions);
                if(name.equals("hello")) {
                    visitor=new MethodVisitor(Opcodes.ASM5, visitor) {
                        Label exceptionHandler;
                        @Override
                        public void visitLabel(Label label) {
                            super.visitLabel(label);
                            if(label==exceptionHandler) {
                                super.visitInsn(Opcodes.DUP);
                                super.visitMethodInsn(Opcodes.INVOKESTATIC, className,
                                    "passException", "(Ljava/lang/Exception;)V", false);
                            }
                        }
                        @Override
                        public void visitTryCatchBlock(
                            Label start, Label end, Label handler, String type) {
                            exceptionHandler=handler;
                            super.visitTryCatchBlock(start, end, handler, type);
                        }
                    };
                }
                return visitor;
            }
        }, ClassReader.SKIP_FRAMES|ClassReader.SKIP_DEBUG);
        byte[] code=classWriter.toByteArray();
        Method def=ClassLoader.class.getDeclaredMethod(
            "defineClass", String.class, byte[].class, int.class, int.class);
        def.setAccessible(true);
        Class<?> instrumented=(Class<?>)def.invoke(
            outer.getClassLoader(), outer.getName()+"$Victim", code, 0, code.length);
        Method hello=instrumented.getMethod("hello", boolean.class);
        System.out.println("invoking "+hello+" with false");
        hello.invoke(null, false);
        System.out.println("invoking "+hello+" with true");
        hello.invoke(null, true);
    }
}
As you can see, it’s straight-forward, just record the exception handler’s label in the visitTryCatchBlock and inject the desired code right after encountering the code position in visitLabel. The rest is the bulk code to read and transform the class file and load the result for testing purpose.
If you use the Tree API in ASM you can get the class's MethodNode and then the MethodNode's instructions (InsnList). Using the InsnList's toArray() method you can iterate through individual instructions. To edit instructions you would do something like this:
for (MethodNode method : classNode.methods) {
    method.instructions.set(insn, otherInsn); // Sets the instruction to another one
    method.instructions.remove(insn); //Removes a given instruction
    method.instructions.add(insn); //Appends to end
    method.instructions.insert(insn, otherInsn); // Inserts an instruction after the given insn
    method.instructions.insertBefore(insn, otherInsn); // Inserts an instruction before the given insn
}
Personally I find this the easiest way to edit method bodies.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With