ASM基础教程-方法

举报
JavaEdge 发表于 2021/06/03 23:38:08 2021/06/03
【摘要】 本文解释如何用核心 ASM API 生成和转换已编译的方法。首先介绍编译后的方法,然后介绍 用于生成和转换它们的相应 ASM 接口、组件和工具,并给出大量说明性示例。看 1 结构 在编译类的内部,方法的代码存储为一系列的字节码指令。 要生成和转换类,最根本的就是要了解这些指令,并理解它们是如何工作的。 本节将对这些指令进行全面概述,这些内容足以开始编写简单的类生成...

本文解释如何用核心 ASM API 生成和转换已编译的方法。首先介绍编译后的方法,然后介绍
用于生成和转换它们的相应 ASM 接口、组件和工具,并给出大量说明性示例。看

1 结构

在编译类的内部,方法的代码存储为一系列的字节码指令。

要生成和转换类,最根本的就是要了解这些指令,并理解它们是如何工作的。
本节将对这些指令进行全面概述,这些内容足以开始编写简单的类生成器与转换器代码。如需完整定义,应当阅读 Java 虚拟机规范。

1.1 执行模型

先来介绍 Java 虚拟机执行模型。
我们知道,Java 代码是在线程内部执行的。每个线程都有自己的执行栈,栈由帧组成。每个帧表示一个方法调用:

  • 每次调用一个方法时,会将一个新帧压入当前线程的执行栈
  • 当方法返回时,或者是正常返回,或者是因为异常返回,会将这个帧从执行栈中弹出,
  • 执行过程在发出调用的方法中继续进行(这个方法的帧现在位于栈的顶端)。

每一帧包括两部分:

  • 一个局部变量部分
  • 一个操作数栈部分

局部变量部分包含可根据索引
以随机顺序访问的变量。由名字可以看出,操作数栈部分是一个栈,其中包含了供字节代码指令
用作操作数的值。这意味着这个栈中的值只能按照“后入先出”顺序访问。不要将操作数栈和线
程的执行栈相混淆:执行栈中的每一帧都包含自己的操作数栈。
局部变量部分与操作数栈部分的大小取决于方法的代码。这一大小是在编译时计算的,并随
字节代码指令一起存储在已编译类中。因此,对于对应于某一给定方法调用的所有帧,其局部变
量与操作数栈部分的大小相同,但对应于不同方法的帧,这一大小可能不同。

一些基本示例,具体体会一下字节代码指令是如何工作的。考虑下面的 bean 类:

package pkg; 
public class Bean { 
 private int f; 
 public int getF() { 
 return this.f; 
 } 
 public void setF(int f) { 
 this.f = f; 
 } 
} 

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

getter 方法的字节代码为:
ALOAD 0
GETFIELD pk如果 mv 是一个 Met

hodVisitor,则 3.1.3 节定义的 getF 方法的字节代码可以用以下方
法调用生成:

mv.visitCode(); 
mv.visitVarInsn(ALOAD, 0); 
mv.visitFieldInsn(GETFIELD, "pkg/Bean", "f", "I"); 
mv.visitInsn(IRETURN); 
mv.visitMaxs(1, 1); 
mv.visitEnd();

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

文章来源: javaedge.blog.csdn.net,作者:JavaEdge.,版权归原作者所有,如需转载,请联系作者。

原文链接:javaedge.blog.csdn.net/article/details/105293421

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。