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

asm 4.0 版本

http://forge.ow2.org/plugins/scmsvn/index.php?group_id=23

 

asm是java的字节码操作框架,可以动态查看类的信息,动态修改,删除,增加类的方法。

 

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


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);//新增加一个方法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);  //調用changeMethodContent,修改方法內容System.out.println("*************");exampleClass.getMethods()[1].invoke(null, null); //調用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)) { //当方法名为execute时,修改方法名为execute1return cv.visitMethod(access, name + "1", desc, signature, exceptions);}if("changeMethodContent".equals(name))  //此处的changeMethodContent即为需要修改的方法  ,修改方法內容{  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;}}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() {       //此方法在访问方法的头部时被访问到,仅被访问一次//此处可插入新的指令super.visitCode();}@Overridepublic void visitInsn(int opcode) {     //此方法可以获取方法中每一条指令的操作类型,被访问多次//如应在方法结尾处添加新指令,则应判断: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

我们把最终的字节码保存到文件中e:\\logs\\Example.class中,再用反编译工具java decompiler 查看最终的生成的源码:

 

最终的类如下:


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!");}
}

接下来再慢慢研究asm里面对字节码的操作,还有其他框架是如果使用asm的。

转载于:https://www.cnblogs.com/zhwj184/archive/2012/08/13/3027473.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/494794.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vim基本命令

最实用的几个&#xff1a; 0&#xff08;数字0&#xff09;移动到本行第一个字符上 $ 移动到行尾 。 3$ 移动到下面3行的行尾 gg 移动到文件头。 [[ G&#xff08;shift g&#xff09; 移动到文件尾。 ]] /text  查找text&#xff0c;按n健查找下一个&#xff0c;按…

map的详解及常见面试题

map的概念 map是STL中的一个关联式容器&#xff0c;它提供一对一的K-V的数据处理能力&#xff0c;由于这个特性&#xff0c;在我们需要完成Key-Value数据处理的时候可以很方便的调用。map的底层结构是红黑树&#xff0c;这棵树对数据有自动排序的功能&#xff0c;所以map中的数…

无处不在的人工智能,IBM沃森的20个行业应用

来源&#xff1a;资本实验室聚焦前沿科技创新与传统产业升级自2011年在美国综艺电视节目《危险边缘》中一战成名后&#xff0c;IBM的Watson就一直是最受关注的人工智能之一。从菜谱分析到球队管理&#xff0c;从健康顾问到酒店礼宾服务&#xff0c;Watson基于自然语言处理和机器…

自定义店招应该具有的基本功能

今天正式开始制作我的第一套SDK2.0模板。 首先是制作店铺的招牌&#xff0c;因为我个人习惯把首页的样式先制作在PSD中&#xff0c;然后参照PSD&#xff0c;由上至下进行编码实现&#xff01;在此前&#xff0c;我一度想过使用默认的店招&#xff0c;但是他真的是太不方便了&a…

一篇文章搞懂数据仓库:数据仓库架构-Lambda和Kappa对比

在介绍Lambda和Kappa架构之前&#xff0c;我们先回顾一下数据仓库的发展历程&#xff1a; 传送门-数据仓库发展历程 写在前面 咳&#xff0c;随着数据量的暴增和数据实时性要求越来越高&#xff0c;以及大数据技术的发展驱动企业不断升级迭代&#xff0c;数据仓库架构方面也在…

epoll精讲

epoll - I/O event notification facility 在linux的网络编程中&#xff0c;很长的时间都在使用select来做事件触发。在linux新的内核中&#xff0c;有了一种替换它的机制&#xff0c;就是epoll。 相比于select&#xff0c;epoll最大的好处在于它不会随着监听fd数目的增长而降…

宇宙和你,本质上其实只是个八维数字?

剑桥大学的数学物理学家Cohl Furey正在寻找粒子物理标准模型和八元数之间的联系。八元数的乘法规则被编码在被称为法诺面的三角图中。来源&#xff1a; 环球科学对于一维、二维乃至四维的数字&#xff0c;人们都不陌生&#xff1a;一维的实数一直都存在于经典物理中&#xff0c…

Fedora 安装QQ2012

1.下载软件包&#xff1a;http://www.everbox.com/f/yLDb2jlpP9WBVvXlSkzC5JKuD9 2.依次执行一下命令 cd /root # 文件存储路径 tar -zxvf qq2012.tar.gz -C /opt # 解压到/opt路径下&#xff0c;注意权限 cd /opt ls cd qq2012/wineapp/qq/ ls ./ins…

一篇文章搞懂数据仓库:数据应用--OLAP

目录 1、OLAP和OLTP的区别 2、OLAP分类 3、OLAP基本操作 4、OLAP选型 1、olap和oltp的区别 OLTPOLAP对象业务开发人员分析决策人员功能日常事务处理面向分析决策模型关系模型多维模型数据量几条或几十条记录&#xff1e;百万于万条记录操作类型增、删、查、改(CRUD)查询为主…

欧洲、美国、中国智慧城市的不同实践路径

来源&#xff1a;远望智库摘要&#xff1a;随着ICT、大数据、物联网等各类新兴技术的不断发展&#xff0c;智慧城市的运营和实践也不断趋于成熟。随着ICT、大数据、物联网等各类新兴技术的不断发展&#xff0c;智慧城市的运营和实践也不断趋于成熟。通过整理欧美各大典型智慧城…

使用IOUtils和FileUtils

文本输出应该比较常用&#xff0c;以前都是通过反复的创建InputStream, InputReader, OutputStream, OutputWriter等去输入输出文本&#xff0c;比较麻烦。Apache提供了一个commons-io.jar包&#xff0c;里面有很多IO相关的工具&#xff0c;比如输入输出文本等&#xff0c;着实…

一个sql生成hive日期维度表

目录 1、日期维度表 2、生成语句 3、用例 在进行日期处理时&#xff0c;有时候会很麻烦&#xff0c;于是小编开发了一张日期维表&#xff0c;供大家参考。 1、日期维度表 num字段名字段中文名描述数据类型1date日期日期 yyyMMdd格式bigint2week星期&#xff0c;数字型星期…

重磅推荐:机器人行业深度报告

来源&#xff1a;WPR随着中国人口红利消失&#xff0c;机器人不仅在制造业上正在替代工人&#xff0c;还将在军事、服务、娱乐等领域取代人类&#xff0c;“钢铁侠”已不仅仅存在于美国科幻电影中&#xff0c;而正走入我们的生活。本篇报告对机器人行业及龙头上市公司进行分析&…

Could not create directory F:\Qt\Test\Error in Util.asciify(build-First_02-Desktop_Qt_5_6_3_Min

第一次使用的Qt的时候出现了这种错误&#xff01; 相信很多人在第一次使用的时候都会遇到这样的情况&#xff0c;果不其然&#xff0c;搜了一下很多的处理方法&#xff0c;其中有一种我感觉是最有效的&#xff0c;就是改一下他的生成路径就好了&#xff0c;因为这个错误的出现…

POJ 2392 Space Elevator

题目地址&#xff1a;http://poj.org/problem?id2392 题目大意&#xff1a;有一头奶牛要上太空&#xff0c;他有很多种石头&#xff0c;每种石头的高度是hi&#xff0c;但是不能放到ai之上的高度&#xff0c;并且这种石头有ci个 将这些石头叠加起来&#xff0c;问能够达到的最…

一篇文章搞懂数据仓库:总线架构、一致性维度、一致性事实

目录 1、概述 总线架构 一致性维度 一致性事实 2、总线架构demo 1、概述 在Kimball的维度建模的数据仓库中&#xff0c;关于多维体系结构&#xff08;MD&#xff09;有三个关键性概念&#xff1a;总线架构&#xff08;Bus Architecture&#xff09;&#xff0c;一致性维…

路易斯·罗森伯格与「群体智能」

选自 | Gigaom编译 | 网易智能&#xff08;smartman163&#xff09;参与 | 李擎与谷歌、Facebook等开发“传统意义上的人工智能”的技术不同&#xff0c;在Unanimous A.I.&#xff0c;科学家们利用人工智能来放大群体的智慧&#xff0c;而不是使用人工智能来代替人类。他们没有…

数据结构和数据类型之间的关系

数据结构 数据元素 数据关系&#xff1b; 数据类型 数据结构 数据操作&#xff1b; 所以数据类型的范畴是大于数据结构的。 数据类型的范畴和类有点相似。其实类也是一种数据类型。 int,char基本类型 同样可以抽象成数据结构和数据元素的模型&#xff0c;只是这里的数据元素…

hive 参数设置大全

合理设置参数&#xff0c;让集群飞起来~ 参数缺省值描述可单独使用set hive.execution.enginetez; 设置hive的计算引擎可单独使用set mapreduce.map.memory.mb4096; 设置每个map的内存可单独使用set mapreduce.reduce.memory.mb4096; 设置每个reduce的内存可单独使用set map…

Qt实用快捷键(较全面)

总结整理的常用快捷键&#xff0c;欢迎留言补充&#xff01;