日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

asm字节码操作 方法的动态修改增加

發(fā)布時(shí)間:2024/7/19 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。