Skip to content

Instantly share code, notes, and snippets.

@VijayKrishna
Last active September 8, 2023 19:53
Show Gist options
  • Save VijayKrishna/1ca807c952187a7d8c4d to your computer and use it in GitHub Desktop.
Save VijayKrishna/1ca807c952187a7d8c4d to your computer and use it in GitHub Desktop.
Example code showing how the AdviceAdapter in ASM(.ow2.org) can be used/extended.
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.
}
}
}
@VijayKrishna
Copy link
Author

note that this code snippet is not yet tested.

@camhart
Copy link

camhart commented Mar 17, 2015

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.

@VijayKrishna
Copy link
Author

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!

@Pasupathi-Rajamanickam
Copy link

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()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment