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

相关文章

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

动态规划---打家劫舍

题目: 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。 思路: 动态规划五部曲: 1.确定dp数组及含义 dp数组是一维数组,dp[i]代表

代码随想录冲冲冲 Day39 动态规划Part7

198. 打家劫舍 dp数组的意义是在第i位的时候偷的最大钱数是多少 如果nums的size为0 总价值当然就是0 如果nums的size为1 总价值是nums[0] 遍历顺序就是从小到大遍历 之后是递推公式 对于dp[i]的最大价值来说有两种可能 1.偷第i个 那么最大价值就是dp[i-2]+nums[i] 2.不偷第i个 那么价值就是dp[i-1] 之后取这两个的最大值就是d

LeetCode:64. 最大正方形 动态规划 时间复杂度O(nm)

64. 最大正方形 题目链接 题目描述 给定一个由 0 和 1 组成的二维矩阵,找出只包含 1 的最大正方形,并返回其面积。 示例1: 输入: 1 0 1 0 01 0 1 1 11 1 1 1 11 0 0 1 0输出: 4 示例2: 输入: 0 1 1 0 01 1 1 1 11 1 1 1 11 1 1 1 1输出: 9 解题思路 这道题的思路是使用动态规划

vue2实践:el-table实现由用户自己控制行数的动态表格

需求 项目中需要提供一个动态表单,如图: 当我点击添加时,便添加一行;点击右边的删除时,便删除这一行。 至少要有一行数据,但是没有上限。 思路 这种每一行的数据固定,但是不定行数的,很容易想到使用el-table来实现,它可以循环读取:data所绑定的数组,来生成行数据,不同的是: 1、table里面的每一个cell,需要放置一个input来支持用户编辑。 2、最后一列放置两个b

Windows下php扩展开发c++动态库

PHP扩展开发,从零了解到初步完成一个小项目,经过三天的仔细研究,现整理如下 一、需求介绍 PHP扩展开发,调用自己之前的c++动态库,完成功能 二、项目之前 系统:windows xp  开发工具:vs 2008 web环境:apache2.4  PHP5.3.29-VC9-ts-x86 aphach和PHP 环境之前已经搭建完成 PHP源码:去官网http://www.php.n

LeetCode:3177. 求出最长好子序列 II 哈希表+动态规划实现n*k时间复杂度

3177. 求出最长好子序列 II 题目链接 题目描述 给你一个整数数组 nums 和一个非负整数k 。如果一个整数序列 seq 满足在下标范围 [0, seq.length - 2] 中 最多只有 k 个下标i满足 seq[i] != seq[i + 1] ,那么我们称这个整数序列为好序列。请你返回 nums中好子序列的最长长度。 实例1: 输入:nums = [1,2,1,1,3],

vue2实践:第一个非正规的自定义组件-动态表单对话框

前言 vue一个很重要的概念就是组件,作为一个没有经历过前几代前端开发的我来说,不太能理解它所带来的“进步”,但是,将它与后端c++、java类比,我感觉,组件就像是这些语言中的类和对象的概念,通过封装好的组件(类),可以通过挂载的方式,非常方便的调用其提供的功能,而不必重新写一遍实现逻辑。 我们常用的element UI就是由饿了么所提供的组件库,但是在项目开发中,我们可能还需要额外地定义一