Java-ASM

我们知道Java是静态语言,而python、ruby是动态语言,Java程序一旦写好很难在运行时更改类的行为,而python、ruby可以。

不过基于bytecode层面上我们可以做一些手脚,来使Java程序多一些灵活性和Magic,ASM就是这样一个应用广泛的开源库。

ASMisaJavabytecodemanipulationframework.Itcanbeusedtodynamicallygeneratestubclassesorotherproxyclasses,

directlyinbinaryform,ortodynamicallymodifyclassesatloadtime,i.e.,justbeforetheyareloadedintotheJavaVirtualMachine.

ASM完成了BCEL和SERP同样的功能,但ASM

只有30多k,而后两者分别是350k和150k。apache真是越来越过气了。

让我们来看一个ASM的简单例子Helloworld.java,它生成一个Example类和一个main方法,main方法打印"Helloworld!"语句:

Java代码

1.importjava.io.FileOutputStream;

2.importjava.io.PrintStream;

3.importorg.objectweb.asm.ClassWriter;

4.importorg.objectweb.asm.MethodVisitor;

5.importorg.objectweb.asm.Opcodes;

6.importorg.objectweb.asm.Type;

7.importorg.objectweb.asm.commons.GeneratorAdapter;

8.importorg.objectweb.asm.commons.Method;

9.

10.publicclassHelloworldextendsClassLoaderimplementsOpcodes{

11.

12.public staticvoid main(finalStringargs[])throwsException{

13.

14.//createsaClassWriterfortheExamplepublicclass,

15.//whichinheritsfromObject

16.

17.ClassWriter cw = newClassWriter(0);

18.cw.visit(V1_1,ACC_PUBLIC,"Example",null,"java/lang/Object",null);

19.MethodVisitormw=cw.visitMethod(ACC_PUBLIC,"<init>","()V",null,

20.null);

21.mw.visitVarInsn(ALOAD,0);

22.mw.visitMethodInsn(INVOKESPECIAL,"java/lang/Object","<init>","()V");

23.mw.visitInsn(RETURN);

24.mw.visitMaxs(1,1);

25.mw.visitEnd();

26.mw=cw.visitMethod(ACC_PUBLIC+ACC_STATIC,"main",

27."([Ljava/lang/String;)V",null,null);

28.mw.visitFieldInsn(GETSTATIC,"java/lang/System","out",

29."Ljava/io/PrintStream;");

30.mw.visitLdcInsn("Helloworld!");

31.mw.visitMethodInsn(INVOKEVIRTUAL,"java/io/PrintStream","println",

32."(Ljava/lang/String;)V");

33.mw.visitInsn(RETURN);

34.mw.visitMaxs(2,2);

35.mw.visitEnd();

36.byte[]code=cw.toByteArray();

37.FileOutputStreamfos=newFileOutputStream("Example.class");

38.fos.write(code);

39.fos.close();

40.Helloworldloader=newHelloworld();

41.ClassexampleClass=loader

42..defineClass("Example",code,0,code.length);

43.exampleClass.getMethods()[0].invoke(null,newObject[]{null});

 

44.//------------------------------------------------------------------------

45.//SameexamplewithaGeneratorAdapter(moreconvenientbutslower)

46.//------------------------------------------------------------------------

47.

48.cw=newClassWriter(ClassWriter.COMPUTE_MAXS);

49.cw.visit(V1_1,ACC_PUBLIC,"Example",null,"java/lang/Object",null);

50.Methodm=Method.getMethod("void<init>()");

51.GeneratorAdaptermg=newGeneratorAdapter(ACC_PUBLIC,m,null,null,

52.cw);

53.mg.loadThis();

54.mg.invokeConstructor(Type.getType(Object.class),m);

55.mg.returnValue();

56.mg.endMethod();

57.m=Method.getMethod("voidmain(String[])");

58.mg=newGeneratorAdapter(ACC_PUBLIC+ACC_STATIC,m,null,null,cw);

59.mg.getStatic(Type.getType(System.class),"out",Type

60..getType(PrintStream.class));

61.mg.push("Helloworld!");

62.mg.invokeVirtual(Type.getType(PrintStream.class),Method

63..getMethod("voidprintln(String)"));

64.mg.returnValue();

65.mg.endMethod();

66.cw.visitEnd();

67.code=cw.toByteArray();

68.loader=newHelloworld();

69.exampleClass=loader.defineClass("Example",code,0,code.length);

70.exampleClass.getMethods()[0].invoke(null,newObject[]{null});

71.}

72.}

 

我们看到上面的例子分别使用ASM的MethodVisitor和GeneratorAdapter两种方式来动态生成Example类并调用打印语句。

 

时间: 2024-12-23 02:04:22

Java-ASM的相关文章

java as给一个类添加属性,并对这个属性赋值,查询操作

问题描述 java as给一个类添加属性,并对这个属性赋值,查询操作 java as给一个类添加属性,并对这个属性赋值,查询操作 ,求大神..................................... 解决方案 你这是 sql 还是 java--看不明白. 解决方案二: 完全看不懂想表达什么啊...... 解决方案三: 如果是查询就select 字段名 as 别名 from 表名. 如果是更新就update 表名 set 字段名='值'. 解决方案四: 如果是查询就select 字段

Java字节码修改框架ASM

字节码相对Java的意义类似汇编相对C的意义,底层了解的越多越深入,程序就越神奇,一切想法皆有可能实现.学习了下字节码框架ASM,总结分享下: API概述. 一.ASM库提供了两类API接口模型来产生或者修改类字节码: (1)核心API: 基于事件,每个事件代表类的一个元素,如头事件.方法事件.字段事件等.特点是更快耗费更少的内存.(2)树型API: 基于对象树状结构,字段方法等都可以看做对象树的一部分.使用相对简单,但耗费内存. 二.API包结构大致如下: (1)事件.解析器.生产器类API在

使用 ASM 实现 Java 语言的“多重继承”

问题的提出 在大部分情况下,需要多重继承往往意味着糟糕的设计.但在处理一些遗留项目的时 候,多重继承可能是我们能做出的选择中代价最小的.由于 Java 语言本身不支持多重继承,这常常会给我们带来麻烦,最后的结果可能就是大量的重复代码.本文试图使用 ASM 框架来解决这一问题.在扩展类的功能的同时,不产生任何重复代码. 考虑如下的实际情况:有一组类,名为 SubClass1.SubClass2.SubClass3 和 SubClass4,它们共同继承了同一个父类 SuperClass.现在,我们需

使用ASM操作Java字节码,实现AOP原理

本文通过一个的例子来实现:使用ASM动态生成Java字节码文件(.class) 或者 加载字节码后动态修改字节码,添加我们需要执行的代码,来模拟实现Spring AOP. 年底了,也没心情抠字了,把写demo包含的几个类代码直接贴出来吧,代码拷贝下来后可以直接使用,不会有什么其他错误. 使用 asm-5.0.3.jar demo工程的package为com.shanhy.demo.asm.hello 5个Java文件: AopClassAdapter.java 用来处理哪些方法需要进行修改 Ao

关于java字节码框架ASM的学习

一.什么是ASM ASM是一个java字节码操纵框架,它能被用来动态生成类或者增强既有类的功能.ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为.Java class 被存储在严格格式定义的 .class文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称.方法.属性以及 Java 字节码(指令).ASM从类文件中读入信息后,能够改变类行为,分析类信息,甚至能够根据用户要求生成新类. 使用ASM框架需要导入asm的jar包,下载链接:

java的cglib动态代理报java.lang.NoSuchMethodError: org.objectweb.asm.ClassWriter

  问题原因 cglib-2.1.3.jar包和asm包冲突     解决办法 将cglib-2.1.3.jar换成cglib-nodep-2.2.2.jar    

java之架构基础-动态代理&amp;amp;cglib

本文核心主要参数动态代理和cglib: 在以前的文章中,有提及到动态代理,它要解决的就是,当我们的某些代码前面或后面都需要一些处理的时候,如写日志.事务控制.做agent.自动化代码跟踪等,此时会给你带来无限的方便,这是JVM级别的提供的一种代理机制,不过在这种机制下调用方法在JVM7出来前还没有invokeDynamic的时候,调用的效率是很低的,此时方法调用都是通过method的invoke去实现. 其基本原理是基于实现JVM提供的一个: InvocationHandler的接口,实现一个方

Greys Java在线问题诊断工具

线上系统为何经常出错?数据库为何屡遭黑手?业务调用为何频频失败?连环异常堆栈案,究竟是那次调用所为? 数百台服务器意外雪崩背后又隐藏着什么?是软件的扭曲还是硬件的沦丧? 走进科学带你了解Greys, Java线上问题诊断工具. Greys的诞生 很早的时候,我们使用BTrace排查问题,在感叹BTrace的强大之余,也曾好几次将线上系统折腾挂掉.2012年淘宝的聚石写了HouseMD,将常用的几个Btrace脚本整合在一起形成一个独立风格的应用,但其核心代码用的是Scala,我们没这方面的编程维

【译】Java 8的新特性—终极版

文/杜琪(简书作者) 原文链接:http://www.jianshu.com/p/5b800057f2d8 著作权归作者所有,转载请联系作者获得授权,并标注"简书作者". 声明:本文翻译自Java 8 Features Tutorial – The ULTIMATE Guide,翻译过程中发现并发编程网已经有同学翻译过了:Java 8 特性 – 终极手册,我还是坚持自己翻译了一版(写作驱动学习,加深印象),有些地方参考了该同学的. Java 8 前言: Java 8 已经发布很久了,很

Java动态代理、cglib动态代理

说动态代理,需要先清楚静态代理.所谓静态代理就是程序员提前实现好的代理类,编译后class文件是已经存在的. 实现原理,利用Java代理模式,由一个代理类持有委托类的实例,并实现委托类一样的接口,来实现增强方法的目的. 我们主要用它来做方法的增强,让你可以在不修改源码的情况下,增强一些方法,在方法执行前后做任何你想做的事情,甚至根本不去执行这个方法.因为在InvocationHandler的invoke方法中,你可以直接获取正在调用方法对应的Method对象.比如可以添加调用日志,做事务控制,对