ASM动态操作方法(增改)

2024-02-13 04:32
文章标签 动态 操作方法 asm 增改

本文主要是介绍ASM动态操作方法(增改),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

下面基于4.2版本的一个使用示例,演示了对类Foo进行修改方法名称,增加方法,修改方法内容等

package myASM;public class Foo {public  void execute(){System.out.println("test changed method name");}public  void changeMethodContent(){System.out.println("test changed method");}
}

 

package myASM;import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;public class MethodChangeClassAdapter extends ClassVisitor implements Opcodes{public MethodChangeClassAdapter(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) {//当方法名为execute时,修改方法名为execute1if (cv != null && "execute".equals(name)){return cv.visitMethod(access, name + "1", desc, signature, exceptions);}//此处的changeMethodContent即为需要修改的方法  ,修改方法內容if("changeMethodContent".equals(name)){//先得到原始的方法MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);MethodVisitor newMethod = null;//访问需要修改的方法newMethod = new AsmMethodVisit(mv); return newMethod;}if (cv != null) {  return cv.visitMethod(access, name, desc, signature, exceptions);  }return null;}
}

 

package myASM;import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;public 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(){//此方法在访问方法的头部时被访问到,仅被访问一次  //此处可插入新的指令  super.visitCode();}@Overridepublic void visitInsn(int opcode){//此方法可以获取方法中每一条指令的操作类型,被访问多次  //如应在方法结尾处添加新指令,则应判断:if(opcode == Opcodes.RETURN){// pushes the 'out' field (of type PrintStream) of the System class mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");// pushes the "Hello World!" String constant mv.visitLdcInsn("this is a modify method!");// invokes the 'println' method (defined in the PrintStream class) mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");}super.visitInsn(opcode);}
}

 

package myASM;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 void main(String args[]) throws IOException, IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, InstantiationException{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);//新增加一个方法MethodVisitor mw = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "add", "([Ljava/lang/String;)V", null, null);mw.visitFieldInsn(GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");mw.visitLdcInsn("this is add method print!");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  // variables  mw.visitMaxs(0, 0);mw.visitEnd();byte[] 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'//調用changeMethodContent,修改方法內容exampleClass.getMethods()[1].invoke(exampleClass.newInstance(), null);System.out.println("***************************");//調用execute,修改方法名 exampleClass.getMethods()[2].invoke(exampleClass.newInstance(), null); // gets the bytecode of the Example class, and loads it dynamically  FileOutputStream fos = new FileOutputStream("e:\\logs\\Example.class");  fos.write(code);  fos.close();}}

 最后在eclipse控制台输出结果:

 

public static void myASM.Foo.add(java.lang.String[])
public void myASM.Foo.changeMethodContent()
public void myASM.Foo.execute1()
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
***************************
test changed method
this is a modify method!
***************************
test changed method name

 

然后通过反编译软件,查看E盘生成的Example.class

 

package myASM;import java.io.PrintStream;public class Foo
{public Foo(){}public void execute1(){System.out.println("test changed method name");}public void changeMethodContent(){System.out.println("test changed method");System.out.println("this is a modify method!");}public static void add(String as[]){System.out.println("this is add method print!");}
}

 

这篇关于ASM动态操作方法(增改)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/704483

相关文章

vue基于ElementUI动态设置表格高度的3种方法

《vue基于ElementUI动态设置表格高度的3种方法》ElementUI+vue动态设置表格高度的几种方法,抛砖引玉,还有其它方法动态设置表格高度,大家可以开动脑筋... 方法一、css + js的形式这个方法需要在表格外层设置一个div,原理是将表格的高度设置成外层div的高度,所以外层的div需要

SpringBoot实现动态插拔的AOP的完整案例

《SpringBoot实现动态插拔的AOP的完整案例》在现代软件开发中,面向切面编程(AOP)是一种非常重要的技术,能够有效实现日志记录、安全控制、性能监控等横切关注点的分离,在传统的AOP实现中,切... 目录引言一、AOP 概述1.1 什么是 AOP1.2 AOP 的典型应用场景1.3 为什么需要动态插

Kafka拦截器的神奇操作方法

《Kafka拦截器的神奇操作方法》Kafka拦截器是一种强大的机制,用于在消息发送和接收过程中插入自定义逻辑,它们可以用于消息定制、日志记录、监控、业务逻辑集成、性能统计和异常处理等,本文介绍Kafk... 目录前言拦截器的基本概念Kafka 拦截器的定义和基本原理:拦截器是 Kafka 消息传递的不可或缺

Linux使用dd命令来复制和转换数据的操作方法

《Linux使用dd命令来复制和转换数据的操作方法》Linux中的dd命令是一个功能强大的数据复制和转换实用程序,它以较低级别运行,通常用于创建可启动的USB驱动器、克隆磁盘和生成随机数据等任务,本文... 目录简介功能和能力语法常用选项示例用法基础用法创建可启动www.chinasem.cn的 USB 驱动

使用SQL语言查询多个Excel表格的操作方法

《使用SQL语言查询多个Excel表格的操作方法》本文介绍了如何使用SQL语言查询多个Excel表格,通过将所有Excel表格放入一个.xlsx文件中,并使用pandas和pandasql库进行读取和... 目录如何用SQL语言查询多个Excel表格如何使用sql查询excel内容1. 简介2. 实现思路3

使用Python处理CSV和Excel文件的操作方法

《使用Python处理CSV和Excel文件的操作方法》在数据分析、自动化和日常开发中,CSV和Excel文件是非常常见的数据存储格式,ython提供了强大的工具来读取、编辑和保存这两种文件,满足从基... 目录1. CSV 文件概述和处理方法1.1 CSV 文件格式的基本介绍1.2 使用 python 内

VUE动态绑定class类的三种常用方式及适用场景详解

《VUE动态绑定class类的三种常用方式及适用场景详解》文章介绍了在实际开发中动态绑定class的三种常见情况及其解决方案,包括根据不同的返回值渲染不同的class样式、给模块添加基础样式以及根据设... 目录前言1.动态选择class样式(对象添加:情景一)2.动态添加一个class样式(字符串添加:情

SpringCloud配置动态更新原理解析

《SpringCloud配置动态更新原理解析》在微服务架构的浩瀚星海中,服务配置的动态更新如同魔法一般,能够让应用在不重启的情况下,实时响应配置的变更,SpringCloud作为微服务架构中的佼佼者,... 目录一、SpringBoot、Cloud配置的读取二、SpringCloud配置动态刷新三、更新@R

SpringBoot操作spark处理hdfs文件的操作方法

《SpringBoot操作spark处理hdfs文件的操作方法》本文介绍了如何使用SpringBoot操作Spark处理HDFS文件,包括导入依赖、配置Spark信息、编写Controller和Ser... 目录SpringBoot操作spark处理hdfs文件1、导入依赖2、配置spark信息3、cont

如何用Python绘制简易动态圣诞树

《如何用Python绘制简易动态圣诞树》这篇文章主要给大家介绍了关于如何用Python绘制简易动态圣诞树,文中讲解了如何通过编写代码来实现特定的效果,包括代码的编写技巧和效果的展示,需要的朋友可以参考... 目录代码:效果:总结 代码:import randomimport timefrom math