asm字节码操作 方法的动态修改增加
生活随笔
收集整理的這篇文章主要介紹了
asm字节码操作 方法的动态修改增加
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
asm 4.0 版本
http://forge.ow2.org/plugins/scmsvn/index.php?group_id=23
?
asm是java的字節(jié)碼操作框架,可以動(dòng)態(tài)查看類(lèi)的信息,動(dòng)態(tài)修改,刪除,增加類(lèi)的方法。
?
下面基于4.0版本的一個(gè)使用示例,演示了對(duì)類(lèi)Foo進(jìn)行修改方法名稱(chēng),增加方法,修改方法內(nèi)容等?
import java.io.FileOutputStream; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;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;public class AsmExample extends ClassLoader implements Opcodes{public static class Foo {public static void execute() {System.out.println("test changed method name");}public static void changeMethodContent() {System.out.println("test change method");}}public static void main(String[] args) throws IOException, IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException {ClassReader cr = new ClassReader(Foo.class.getName());ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);ClassVisitor cv = new MethodChangeClassAdapter(cw);cr.accept(cv, Opcodes.ASM4);//新增加一個(gè)方法MethodVisitor mw= cw.visitMethod(ACC_PUBLIC + ACC_STATIC,"add","([Ljava/lang/String;)V",null,null);// pushes the 'out' field (of type PrintStream) of the System classmw.visitFieldInsn(GETSTATIC,"java/lang/System","out","Ljava/io/PrintStream;");// pushes the "Hello World!" String constantmw.visitLdcInsn("this is add method print!");// invokes the 'println' method (defined in the PrintStream class)mw.visitMethodInsn(INVOKEVIRTUAL,"java/io/PrintStream","println","(Ljava/lang/String;)V");mw.visitInsn(RETURN);// this code uses a maximum of two stack elements and two local// variablesmw.visitMaxs(0, 0);mw.visitEnd();// gets the bytecode of the Example class, and loads it dynamicallybyte[] code = cw.toByteArray();AsmExample loader = new AsmExample();Class<?> exampleClass = loader.defineClass(Foo.class.getName(), code, 0, code.length);for(Method method: exampleClass.getMethods()){System.out.println(method);}System.out.println("*************");// uses the dynamically generated class to print 'Helloworld'exampleClass.getMethods()[0].invoke(null, null); //調(diào)用changeMethodContent,修改方法內(nèi)容System.out.println("*************");exampleClass.getMethods()[1].invoke(null, null); //調(diào)用execute,修改方法名// gets the bytecode of the Example class, and loads it dynamicallyFileOutputStream fos = new FileOutputStream("e:\\logs\\Example.class");fos.write(code);fos.close();}static class MethodChangeClassAdapter extends ClassVisitor implements Opcodes {public MethodChangeClassAdapter(final ClassVisitor cv) {super(Opcodes.ASM4, cv);}@Overridepublic void visit(int version,int access,String name,String signature,String superName,String[] interfaces){if (cv != null) {cv.visit(version, access, name, signature, superName, interfaces);}}@Overridepublic MethodVisitor visitMethod(int access,String name,String desc,String signature,String[] exceptions){if (cv != null && "execute".equals(name)) { //當(dāng)方法名為execute時(shí),修改方法名為execute1return cv.visitMethod(access, name + "1", desc, signature, exceptions);}if("changeMethodContent".equals(name)) //此處的changeMethodContent即為需要修改的方法 ,修改方法內(nèi)容{ MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);//先得到原始的方法 MethodVisitor newMethod = null; newMethod = new AsmMethodVisit(mv); //訪問(wèn)需要修改的方法 return newMethod; } if (cv != null) {return cv.visitMethod(access, name, desc, signature, exceptions);}return null;}}static class AsmMethodVisit extends MethodVisitor {public AsmMethodVisit(MethodVisitor mv) {super(Opcodes.ASM4, mv); }@Overridepublic void visitMethodInsn(int opcode, String owner, String name, String desc) {super.visitMethodInsn(opcode, owner, name, desc);}@Overridepublic void visitCode() { //此方法在訪問(wèn)方法的頭部時(shí)被訪問(wèn)到,僅被訪問(wèn)一次//此處可插入新的指令super.visitCode();}@Overridepublic void visitInsn(int opcode) { //此方法可以獲取方法中每一條指令的操作類(lèi)型,被訪問(wèn)多次//如應(yīng)在方法結(jié)尾處添加新指令,則應(yīng)判斷:if(opcode == Opcodes.RETURN){// pushes the 'out' field (of type PrintStream) of the System classmv.visitFieldInsn(GETSTATIC,"java/lang/System","out","Ljava/io/PrintStream;");// pushes the "Hello World!" String constantmv.visitLdcInsn("this is a modify method!");// invokes the 'println' method (defined in the PrintStream class)mv.visitMethodInsn(INVOKEVIRTUAL,"java/io/PrintStream","println","(Ljava/lang/String;)V"); // mv.visitInsn(RETURN);}super.visitInsn(opcode);}}}
輸出:
?
add方法是新增的,execute方法名改為execute1,changeMethodContent方法修改后增加了輸出this is a modify method!
public static void AsmExample$Foo.changeMethodContent() public static void AsmExample$Foo.execute1() public static void AsmExample$Foo.add(java.lang.String[]) public native int java.lang.Object.hashCode() public final native java.lang.Class java.lang.Object.getClass() public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException public final void java.lang.Object.wait() throws java.lang.InterruptedException public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException public boolean java.lang.Object.equals(java.lang.Object) public java.lang.String java.lang.Object.toString() public final native void java.lang.Object.notify() public final native void java.lang.Object.notifyAll() ************* test change method this is a modify method! ************* test changed method name
我們把最終的字節(jié)碼保存到文件中e:\\logs\\Example.class中,再用反編譯工具java decompiler 查看最終的生成的源碼:
?
最終的類(lèi)如下:
import java.io.PrintStream;public class AsmExample$Foo {public static void execute1(){System.out.println("test changed method name");}public static void changeMethodContent() {System.out.println("test change method");System.out.println("this is a modify method!");}public static void add(String[] paramArrayOfString){System.out.println("this is add method print!");} }
接下來(lái)再慢慢研究asm里面對(duì)字節(jié)碼的操作,還有其他框架是如果使用asm的。
轉(zhuǎn)載于:https://www.cnblogs.com/zhwj184/archive/2012/08/13/3027473.html
總結(jié)
以上是生活随笔為你收集整理的asm字节码操作 方法的动态修改增加的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: jQuery 1.7.1 代码研究 ex
- 下一篇: 使用IOUtils和FileUtils