-
-
Save VijayKrishna/1ca807c952187a7d8c4d to your computer and use it in GitHub Desktop.
package self.vpalepu.stackoverflow; | |
import java.io.File; | |
import java.io.FileInputStream; | |
import java.io.IOException; | |
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 org.objectweb.asm.commons.AdviceAdapter; | |
/** | |
* Class visitor that adapts a java class to insert code before | |
* the return instructions in the methods of the class. | |
* @author vijay | |
* | |
*/ | |
public class ReturnAdapter extends ClassVisitor { | |
private String className; | |
public ReturnAdapter(ClassVisitor cv, String className) { | |
super(Opcodes.ASM4, cv); | |
} | |
@Override | |
public MethodVisitor visitMethod( | |
int access, | |
String name, | |
String desc, | |
String signature, | |
String[] exceptions) { | |
MethodVisitor mv; | |
mv = cv.visitMethod(access, name, desc, signature, exceptions); | |
mv = new MethodReturnAdapter(Opcodes.ASM4, className, access, name, desc, mv); | |
return mv; | |
} | |
public static void main(String[] args) throws IOException { | |
String classFile = args[0];//path of the class file | |
String className = args[1];//name of the class | |
File inFile = new File(classFile); | |
FileInputStream in = new FileInputStream(inFile); | |
// adapting the class. | |
ClassReader cr = new ClassReader(in); | |
ClassWriter cw = new ClassWriter(ClassReader.EXPAND_FRAMES); | |
ReturnAdapter returnAdapter = new ReturnAdapter(cw, className); | |
cr.accept(returnAdapter, 0); | |
} | |
} | |
/** | |
* Method Visitor that inserts code right before its return instruction(s), | |
* using the onMethodExit(int opcode) method of the AdviceAdapter class, | |
* from ASM(.ow2.org). | |
* @author vijay | |
* | |
*/ | |
class MethodReturnAdapter extends AdviceAdapter { | |
public MethodReturnAdapter( | |
int api, | |
String owner, | |
int access, | |
String name, | |
String desc, | |
MethodVisitor mv) { | |
super(Opcodes.ASM4, mv, access, name, desc); | |
} | |
public MethodReturnAdapter( | |
MethodVisitor mv, | |
int access, | |
String name, | |
String desc) { | |
super(Opcodes.ASM4, mv, access, name, desc); | |
} | |
@Override | |
protected void onMethodExit(int opcode) { | |
if(opcode != Opcodes.ATHROW) { | |
mv.visitVarInsn(Opcodes.ALOAD, 42); | |
// and/or any other visit instructions. | |
} | |
} | |
} |
You keep posting this as an answer. Could you clean the code up? At least get it to compile. I'd love to be able to learn from it, but as it is now I'm failing to do so.
I have been busy with paper deadlines these last few weeks. Check back in a couple of days to find better code. Meanwhile, if you want to share the (compile?) error that you are getting, that would be a big help as well!
Can you help me how to use this? I have a class named Hello, it has a method, "sayHello". I did the following in the main method that you have written here.
ByteClassLoader byteClassLoader = new ByteClassLoader();
Class class2 = byteClassLoader.findClass("com.parse.Hello", cw.toByteArray());
System.out.println(class2.getMethods());
System.out.println( ((Hello) class2.newInstance()) .sayHello());
It is showing exception. local variable table overflow in method com.parse.Hello.sayHello()
note that this code snippet is not yet tested.