文章目录

  • 1. ASM 是什么
  • 2. ASM 能够做什么
  • 3. 为什么要学习 ASM
    • 3.1 Spring 当中的 ASM
    • 3.2 JDK 当中的 ASM
  • 4. ASM 的两个组成部分
    • 4.1 Core API
      • 4.1.1 asm.jar
      • 4.1.2 asm-util.jar
      • 4.1.3 asm-commons.jar
  • 5. 搭建 ASM 开发环境
    • 5.1 pom 文件信息
    • 5.2 使用 ASM
      • 5.2.1 预期目标
      • 5.2.2 编码实现
      • 5.2.3 验证结果

1. ASM 是什么

ASM 是一个操作 Java 字节码的类库

  • ASM 所操作的对象是字节码 (ByteCode) 数据
  • ASM 处理字节码 (ByteCode) 的方式是"拆分-修改-合并"
  1. 将.class 文件拆分成多个部分
  2. 对某一个部分的信息进行修改
  3. 将多个部分重新组织成一个新的.class 文件

2. ASM 能够做什么

父类: 修改成一个新的父类
接口: 添加一个新的接口, 删除已有的接口
字段: 添加一个新的字段, 删除已有的字段
方法: 添加一个新的方法, 删除已有的方法, 修改已有的方法

public class HelloWorld extends Object implements Cloneable {public int intValue;public String strValue;public int add(int a, int b) {return a + b;}public int sub(int a, int b) {return a - b;}@Overridepublic Object clone() throws CloneNotSupportedException {return super.clone();}
}

3. 为什么要学习 ASM

ASM 就是一处位于“Java 语言的世界”边界上的一扇大门, 通过这扇大门, 我们可以前往“字节码的世界”, 在“字节码的世界”里, 我们会看到不一样的“风景”, 能够解决不一样的“问题”

ASM 往往在一些框架的底层起着重要的作用, 介绍两个关于 ASM 的应用场景

  • Spring
  • JDK

3.1 Spring 当中的 ASM

Spring 框架的 AOP 是依赖于 ASM 的. 具体来说, Spring 的 AOP, 可以通过 JDK 的动态代理来实现, 也可以通过 CGLIB 实现. 其中, CGLib (Code Generation Library) 是在 ASM 的基础上构建起来的, 所以, Spring AOP 是间接的使用了 ASM

3.2 JDK 当中的 ASM

JDK 当中的 Lambda 表达式, 允许把方法作为参数进行传递, 它能够使代码变的更加简洁紧凑, Lambda 表达式的调用是通过 ASM 来实现的

在 rt.jar 文件的 jdk.internal.org.objectweb.asm 包当中, 就包含了 JDK 内置的 ASM 代码. 在 JDK 8 版本当中, 它所使用的 ASM 5.0 版本

跟踪 Lambda 表达式的编码实现, 就会找到 InnerClassLambdaMetafactory.spinInnerClass() 方法. 在这个方法当中, 我们就会看到: JDK 会使用 jdk.internal.org.objectweb.asm.ClassWriter 来生成一个类, 将 lambda 表达式的代码包装起来

// 第一步, 找到这个方法
LambdaMetafactory.metafactory()// 第二步, 找到这个方法
---> InnerClassLambdaMetafactory.buildCallSite()// 第三步, 找到这个方法---> InnerClassLambdaMetafactory.spinInnerClass()

4. ASM 的两个组成部分

从组成结构上来说, ASM 分成两部分

  • Core API 包括 asm.jar, asm-util.jar 和 asm-commons.jar
  • Tree API 包括 asm-tree.jar 和 asm-analysis.jar

从两者的关系来说, Core API 是基础, 而 Tree API 是在 Core API 的这个基础上构建起来的

4.1 Core API

ASM Core API 包括 asm.jar, asm-util.jar 和 asm-commons.jar

4.1.1 asm.jar

在 asm.jar 文件中, 一共包含了 30 多个类, 重点其中 10 个类, 剩下的 20 多个类是辅助的作用

从无到有生成一个新的类, 其中会涉及到 ClassVisitor, ClassWriter, FieldVisitor, FieldWriter, MethodVisitor, MethodWriter, Label 和 Opcodes 类

修改已有的类, 使之内容发生改变, 其中会涉及到 Cla***eader 和 Type 类

在这 10 个类当中, 最重要的是三个类 Cla***eader, ClassVisitor 和 ClassWriter 类, 这三个类的关系如下

这三个类的作用, 可以简单理解成这样

  • Cla***eader 类, 负责读取.class 文件里的内容, 然后拆分成各个不同的部分
  • ClassVisitor 类, 负责对.class 文件中某一部分里的信息进行修改
  • ClassWriter 类, 负责将各个不同的部分重新组合成一个完整的.class 文件

4.1.2 asm-util.jar

asm-util.jar 主要包含的是一些工具类, 在下图当中可以看到 asm-util.jar 里面包含的具体类文件, 这些类主要分成两种类型

  • 以 Check 开头的类, 主要负责检查 (Check) 生成的.class 文件内容是否正确
  • 以 Trace 开头的类, 主要负责将.class 文件的内容打印成文字输出, 根据输出的文字信息, 可以探索或追踪 (Trace) .class 文件的内部信息

4.1.3 asm-commons.jar

asm-commons.jar 主要包含的是一些常用功能类, 在下图当中, 可以看到 asm-commons.jar 里面包含的具体类文件

asm-util.jar 与 asm-commons.jar 有什么区别呢?

  • 在 asm-util.jar 里, 它提供的是通用性的功能, 没有特别明确的应用场景
  • 在 asm-commons.jar 里, 它提供的功能, 都是为解决某一种特定场景中出现的问题而提出的解决思路

5. 搭建 ASM 开发环境

5.1 pom 文件信息

修改 pom.xml
新建一个 maven 项目, 取名为 asm-maven, 修改其中的 pom.xml 文件, 添加 ASM 的 Jar 包依赖. 打开 pom.xml 文件, 并添加如下内容

<properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><java.version>1.8</java.version><maven.compiler.source>${java.version}</maven.compiler.source><maven.compiler.target>${java.version}</maven.compiler.target><asm.version>9.0</asm.version>
</properties><dependencies><dependency><groupId>org.ow2.asm</groupId><artifactId>asm</artifactId><version>${asm.version}</version></dependency><dependency><groupId>org.ow2.asm</groupId><artifactId>asm-commons</artifactId><version>${asm.version}</version></dependency><dependency><groupId>org.ow2.asm</groupId><artifactId>asm-util</artifactId><version>${asm.version}</version></dependency><dependency><groupId>org.ow2.asm</groupId><artifactId>asm-tree</artifactId><version>${asm.version}</version></dependency><dependency><groupId>org.ow2.asm</groupId><artifactId>asm-analysis</artifactId><version>${asm.version}</version></dependency>
</dependencies><build><plugins><!-- Java Compiler --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>${java.version}</source><target>${java.version}</target><fork>true</fork><compilerArgs><arg>-g</arg><arg>-parameters</arg></compilerArgs></configuration></plugin></plugins>
</build>

5.2 使用 ASM

对 ASM 的使用有一个初步的认识, 为了验证 ASM 的开发环境是能够正常使用的

5.2.1 预期目标

我们的预期目标是, 生成一个 HelloWorld 类, 它对应的 Java 代码如下

public class HelloWorld {@Overridepublic String toString() {return "This is a HelloWorld object.";}
}

注意, 我们不需要去写这样一个 sample/HelloWorld.java 文件, 只是生成的 HelloWorld 类和这里的 Java 代码是一样的效果

5.2.2 编码实现

public class HelloWorldDump implements Opcodes {public static byte[] dump() {ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);cw.visit(V1_8, ACC_PUBLIC | ACC_SUPER, "sample/HelloWorld", null, "java/lang/Object", null);{MethodVisitor mv1 = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);mv1.visitCode();mv1.visitVarInsn(ALOAD, 0);mv1.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);mv1.visitInsn(RETURN);mv1.visitMaxs(1, 1);mv1.visitEnd();}{MethodVisitor mv2 = cw.visitMethod(ACC_PUBLIC, "toString", "()Ljava/lang/String;", null, null);mv2.visitCode();mv2.visitLdcInsn("This is a HelloWorld object.");mv2.visitInsn(ARETURN);mv2.visitMaxs(1, 1);mv2.visitEnd();}cw.visitEnd();return cw.toByteArray();}
}

5.2.3 验证结果

public class MyClassLoader extends ClassLoader {@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {if ("sample.HelloWorld".equals(name)) {byte[] bytes = HelloWorldDump.dump();Class<?> clazz = defineClass(name, bytes, 0, bytes.length);return clazz;}throw new ClassNotFoundException("Class Not Found: " + name);}
}public class HelloWorldRun {public static void main(String[] args) throws Exception {MyClassLoader classLoader = new MyClassLoader();Class<?> clazz = classLoader.loadClass("sample.HelloWorld");Object instance = clazz.newInstance();System.out.println(instance);}
}

运行之后的输出结果 This is a HelloWorld object

[20][05][01] ASM介绍相关推荐

  1. 2019年TI杯 简易电路特性测试仪 制作过程(6)——测量任务分析(Av、fH) 20/05/01

    一.增益Av测量 1.增益Av测量--采样 uint8_t AV_Sample_1KHz_Handle(void) {uint8_t res = 0;if(Measure_Av_Jun.Uo_ave_ ...

  2. Python小白的数学建模课-05.0-1规划

    0-1 规划不仅是数模竞赛中的常见题型,也具有重要的现实意义. 双十一促销中网购平台要求二选一,就是互斥的决策问题,可以用 0-1规划建模. 小白学习 0-1 规划,首先要学会识别 0-1规划,学习将 ...

  3. html5学习笔记---01.HTML5介绍,02.HTML5的新特性

    2013/6/10 01.HTML5介绍 a.创梦技术qq交流群:CreDream:251572072 -------------------- a.创梦技术qq交流群:CreDream:251572 ...

  4. 20.1 shell脚本介绍 20.2 shell脚本结构和执行 20.3 date命令用法 20.4 shell脚本中的变量...

    2019独角兽企业重金招聘Python工程师标准>>> 20.1 shell脚本介绍 shell 是一种脚本语言:和传统的开发语言比较,会比较简单 shell有自己的语法:可以使用逻 ...

  5. 乐视网CEO梁军:现在就是缺钱 正在重新学习做生意 2017年09月20日01:18 新京报 37 微博 微信 QQ空间 添加喜爱 乐视网CEO梁军。 新京报记者 吴江 摄乐视网CEO梁军。 新京

    乐视网CEO梁军:现在就是缺钱 正在重新学习做生意 2017年09月20日01:18 新京报 37微博微信QQ空间添加喜爱 乐视网CEO梁军. 新京报记者 吴江 摄 乐视网(15.330, 0.00, ...

  6. Galaxy Release 20.05 发布,新增多项可视化体验

    Galaxy Project(https://galaxyproject.org/)是在云计算背景下诞生的一个生物信息学可视化分析开源项目. 该项目由美国国家科学基金会(NSF).美国国家人类基因组研 ...

  7. vue.js 2.0 官方文档学习笔记 —— 01. vue 介绍

    这是我的vue.js 2.0的学习笔记,采取了将官方文档中的代码集中到一个文件的形式.目的是保存下来,方便自己查阅. !官方文档:https://cn.vuejs.org/v2/guide/ 01. ...

  8. asm 查看 数据文件 修改 时间_Oracle的ASM介绍及管理

    Oracle的ASM介绍及管理 Oracle经历过的文件系统历史 操作系统--逻辑卷管理器(LVM):管理文件相对容易,性能较差 裸设备:管理文件相对困难,性能好 OCFS(Oracle Cluste ...

  9. FD.io VPP 20.05 官方文档 总目录:用户文档+开发文档+命令行

    https://docs.fd.io/vpp/20.05/index.html Vector Packet Processing FD.io VPP ▼Vector Packet Processing ...

最新文章

  1. Spring Cloud(五)断路器监控(Hystrix Dashboard)
  2. 性能加速最高可达28倍!这个NLP工具包太NB了!
  3. Python 循环拼接字符串_详解Python拼接字符串的七种方式
  4. JavaScript中的作用域,闭包和上下文
  5. ASP.NET jQuery 食谱15 (通过控件CustomValidator验证CheckBoxList)
  6. Java学习日报—注解、Hash、Lombok—2021/12/02
  7. 打开帧率显示_2K165hz IPS屏,微星MAG274QRF-QD显示器
  8. 常见的特殊字符和HTML之间的对应关系~
  9. 超分辨率谷歌卫星图下载经验贴
  10. Revisiting RCNN: On Awakening the Classification Power of Faster RCNN解读
  11. 熊出没机器人光头强_熊出没中光头强太迂腐,这4种物品都能让他身价过亿,却弃而不用...
  12. 怎么注册自定义域名Email.cn邮箱?
  13. Web前端期末大作业-农产品一体化平台网页设计(HTML+CSS+JS)
  14. android 内存至少一半,极客修:为什么iPhone比安卓内存小,却更流畅?
  15. 程序员的自我修养(十五)-线程 - TLS
  16. 开放式耳机新巅峰!南卡OE Pro兼备澎湃音质、舒适佩戴、创新设计
  17. C语言关于输入某天日期求是本年第几天(计算天数)
  18. 语音信号端点检测 matlab,matlab中语音端点检测
  19. 【PE结构】由浅入深PE基础学习-菜鸟手动查询导出表、相对虚拟地址(RVA)与文件偏移地址转换(FOA)...
  20. 解决vscode红色波浪线的ts报错:找不到模块“store” ts(2307),不识别@别名路径

热门文章

  1. 哈工大计算机学院奖学金,【逆天了】哈工大研究生补贴/奖学金一览表,原来读研福利这么好...
  2. C++注释的几种方法
  3. 【软件构造】equals()、hashCode()及引用等价性、对象等价性、观察等价性、行为等价性
  4. docker学习——bind mounts
  5. fitbit手表中文说明书_最佳Fitbit:哪一个适合您?
  6. 在斩获“数据金羊毛”的途中,易观造船现行,人称Argo号~
  7. 每日安全简讯20160721
  8. Windows平台分布式架构实践 - 负载均衡
  9. 超700名研究生被清退,硕博生毕业,更难了
  10. 三调 图斑地类面积_图斑地类面积理论值计算方法说明