Java字节码操纵框架。它可以直接以二进制形式动态地生成stub类或其他代理类,或者在装载时动态地修改类。ASM提供类似于BCEL和SERP之类的工具包的功能,但是被设计得更小巧、更快速,这使它适用于实时代码插装。

.NET/liyangbing315/article/details/5472862
你可以利用ASM动态操作class

我们知道Java是静态语言,而Python、ruby是动态语言,Java程序一旦写好很难在运行时更改类的行为,而Python、ruby可以。 
不过基于bytecode层面上我们可以做一些手脚,来使Java程序多一些灵活性和Magic,ASM就是这样一个应用广泛的开源库。

ASM is a Java bytecode manipulation framework. It can be used to dynamically generatestub classes
or other proxy classes, 
directly in binary form, or to dynamically modify classes at load time, i.e., justbefore they are loaded into the Java 
Virtual Machine.

ASM完成了BCELSERP同样的功能,但ASM 
只有30多k,而后两者分别是350k和150k。apache真是越来越过气了。

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

Java代码

  1. import java.io.FileOutputStream;
  2. import java.io.PrintStream;
  3. import org.objectweb.asm.ClassWriter;
  4. import org.objectweb.asm.MethodVisitor;
  5. import org.objectweb.asm.Opcodes;
  6. import org.objectweb.asm.Type;
  7. import org.objectweb.asm.commons.GeneratorAdapter;
  8. import org.objectweb.asm.commons.Method;
  9. public class Helloworld extends ClassLoader implements Opcodes
    {
  10. public static void main(final String args[]) throws Exception
    {
  11. // creates a ClassWriter for the Example public class,
  12. // which inherits from Object
  13. ClassWriter cw = new ClassWriter(0);
  14. cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);
  15. MethodVisitor mw = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null,
  16. null);
  17. mw.visitVarInsn(ALOAD, 0);
  18. mw.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
  19. mw.visitInsn(RETURN);
  20. mw.visitMaxs(1, 1);
  21. mw.visitEnd();
  22. mw = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "main",
  23. "([Ljava/lang/String;)V", nullnull);
  24. mw.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
  25. "Ljava/io/PrintStream;");
  26. mw.visitLdcInsn("Hello world!");
  27. mw.visitMethodInsn(INVOKEVIRTUAL, "java/io/PrintStream", "println",
  28. "(Ljava/lang/String;)V");
  29. mw.visitInsn(RETURN);
  30. mw.visitMaxs(2, 2);
  31. mw.visitEnd();
  32. byte[] code = cw.toByteArray();
  33. FileOutputStream fos = new FileOutputStream("Example.class");
  34. fos.write(code);
  35. fos.close();
  36. Helloworld loader = new Helloworld();
  37. Class exampleClass = loader
  38. .defineClass("Example", code, 0, code.length);
  39. exampleClass.getMethods()[0].invoke(nullnew Object[] { null });
  40. // ------------------------------------------------------------------------
  41. // Same example with a GeneratorAdapter (more convenient but slower)
  42. // ------------------------------------------------------------------------
  43. cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
  44. cw.visit(V1_1, ACC_PUBLIC, "Example", null, "java/lang/Object", null);
  45. Method m = Method.getMethod("void <init> ()");
  46. GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, nullnull,
  47. cw);
  48. mg.loadThis();
  49. mg.invokeConstructor(Type.getType(Object.class), m);
  50. mg.returnValue();
  51. mg.endMethod();
  52. m = Method.getMethod("void main (String[])");
  53. mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, nullnull, cw);
  54. mg.getStatic(Type.getType(System.class), "out", Type
  55. .getType(PrintStream.class));
  56. mg.push("Hello world!");
  57. mg.invokeVirtual(Type.getType(PrintStream.class), Method
  58. .getMethod("void println (String)"));
  59. mg.returnValue();
  60. mg.endMethod();
  61. cw.visitEnd();
  62. code = cw.toByteArray();
  63. loader = new Helloworld();
  64. exampleClass = loader.defineClass("Example", code, 0, code.length);
  65. exampleClass.getMethods()[0].invoke(nullnew Object[] { null });
  66. }
  67. }

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

asm-3.3.1.jar详解 (转)的更多相关文章

  1. 转:关于将Java编译过的.class文件打成jar可执行文件/JAR详解

    原文链接:关于将Java编译过的.class文件打成jar可执行文件/JAR详解 如何把 java 程序编译成 .exe 文件.通常回答只有两种,一种是制作一个可执行的 JAR 文件包,然后就可以像. ...

  2. eclipse生成export生成jar详解

    使用eclipse打jar包可能还有很多人不是很了解,今天特意测试整理一番. 打jar包有3种形式 JAR file               JAR Javadoc              ja ...

  3. Oracle 10g RAC (linux) ASM 共享存储的管理详解

    ---------ASM 的管理(共享磁盘的管理)1.以 instance 的方式管理 ASM,启动 database 之前必须先启动 ASM instance,ASM instance 启动后,挂载 ...

  4. Spring jar包详解

    Spring jar包详解 org.springframework.aop ——Spring的面向切面编程,提供AOP(面向切面编程)的实现 org.springframework.asm——spri ...

  5. Spring——jar包详解(转)

    Spring——jar包详解 org.springframework.aop ——Spring的面向切面编程,提供AOP(面向切面编程)的实现 org.springframework.asm——spr ...

  6. Spring 3.x jar 包详解 与 依赖关系

    以下的内容我会持续更新(当然是我有新发现的时候); 以下内容是我在网上搜索.整理.修改的而成的内容.由于很多内容都是转载了,无法追溯到源头,因此无法一一对原作者进行道谢. 这几天,我查阅大量的官方的文 ...

  7. Spring 3.x jar 包详解 与 依赖关系(转)

    以下的内容我会持续更新(当然是我有新发现的时候); 以下内容是我在网上搜索.整理.修改的而成的内容.由于很多内容都是转载了,无法追溯到源头,因此无法一一对原作者进行道谢. 这几天,我查阅大量的官方的文 ...

  8. 常见 jar包详解

        常见 jar包详解 jar包 用途 axis.jar SOAP引擎包 commons-discovery-0.2.jar 用来发现.查找和实现可插入式接口,提供一些一般类实例化.单件的生命周期 ...

  9. Spring各个jar包详解

    Spring各jar包详解 spring.jar 是包含有完整发布模块的单个jar 包.但是不包括mock.jar,aspects.jar, spring-portlet.jar, and sprin ...

随机推荐

  1. JQuery 操作数组 each、map、grep

    Jquery中对数组的操作大致有一下几种形式:1.$.each( collection, callback(indexInArray, valueOfElement) )$.each()函数和$(se ...

  2. EXSI5.5以上开启KVM二次虚拟化

    1,在EXSI5.5上创建centos虚拟机(过程省略) 2,开启EXSI5.5的ssh功能 3,ssh登录虚拟机 4,编辑虚拟配置文件 /vmfs/volumes/datastore1/目录下,找到 ...

  3. JS获取时间戳+C#水煎戳转换

    JS获取了当前毫秒的时间戳. var timestamp=new Date().getTime(); //第二种方法: //var timestamp = (new Date()).valueOf() ...

  4. webPage logService 日志服务 剥离

    [旧的场景]1.x.a.com指向负载均衡服务器ipL;2.代码所在的应用服务器ipA,ipB,ipC,运行nginx-phpFPM服务,提供2个服务: 2.1.应用服务器ipA,ipB,ipC中we ...

  5. netty4.x 实现接收http请求及响应

    参考 netty4.x 实现接收http请求及响应 - En taro tassadar - CSDN博客 https://blog.csdn.net/sinat_39783636/article/d ...

  6. Sqoop简介及使用

    一.Sqoop概述 1)官网 http://sqoop.apache.org/ 2)场景 传统型缺点,分布式存储.把传统型数据库数据迁移. Apache Sqoop(TM)是一种用于在Apache H ...

  7. c++拷贝构造函数,深拷贝,浅拷贝,对象内存

    https://blog.csdn.net/lwbeyond/article/details/6202256 防止默认拷贝发生 通过对对象复制的分析,我们发现对象的复制大多在进行“值传递”时发生,这里 ...

  8. requests+BeautifulSoup详解

    简介 Python标准库中提供了:urllib.urllib2.httplib等模块以供Http请求,但是,它的 API 太渣了.它是为另一个时代.另一个互联网所创建的.它需要巨量的工作,甚至包括各种 ...

  9. 【Django错误】OSError: raw write() returned invalid length 14 (should have been between 0 and 7)

    错误环境 使用Django框架创建完models类的之后,用python manage.py migrate命令来生成数据库表的时候出错 错误代码 Operations to perform: App ...

  10. Spring第七弹—依赖注入之注解方式注入及编码解析@Resource原理

        注入依赖对象可以采用手工装配或自动装配,在实际应用中建议使用手工装配,因为自动装配会产生未知情况,开发人员无法预见最终的装配结果. 手工装配依赖对象  手工装配依赖对象,在这种方式中又有两种编 ...