java map堆栈_java – 什么是堆栈映射框架

Java要求验证所有加载的类,以便维护沙箱的安全性并确保代码可以安全地进行优化.请注意,这是在字节码级别完成的,因此验证不会验证Java语言的不变量,它只是根据字节码规则验证字节码是否有意义.

除此之外,字节码验证可确保指令格式正确,所有跳转都是方法中的有效指令,并且所有指令都对正确类型的值进行操作.最后一个是堆栈映射的来源.

问题是字节码本身不包含显式类型信息.通过数据流分析隐式确定类型.例如,iconst指令创建一个整数值.如果将其存储在插槽1中,则该插槽现在具有int.如果控制流从存储浮点的代码合并而来,则现在认为该槽具有无效类型,这意味着在覆盖它之前,您不能再使用该值执行任何操作.

从历史上看,字节码验证器使用这些数据流规则推断出所有类型.不幸的是,不可能通过字节码推断单个线性传递中的所有类型,因为向后跳转可能使已经推断的类型无效.经典验证程序通过迭代代码直到一切都停止变化来解决这个问题,可能需要多次传递.

但是,验证使Java中的类加载速度变慢. Oracle决定通过添加一个新的,更快的验证器来解决这个问题,它可以在一次通过中验证字节码.为此,他们需要从Java 7开始的所有新类(Java 6处于过渡状态)携带有关其类型的元数据,以便可以一次性验证字节码.由于字节码格式本身无法更改,因此此类型信息单独存储在名为StackMapTable的属性中.

简单地在代码中的每个单点存储每个值的类型显然会占用大量空间并且非常浪费.为了使元数据更小更高效,他们决定让它只列出跳转目标位置的类型.如果您考虑一下,这是您需要额外信息才能进行单程验证的唯一时间.在跳转目标之间,所有控制流都是线性的,因此您可以使用旧的推理规则推断位置之间的类型.

显式列出类型的每个位置称为堆栈映射帧. StackMapTable属性按顺序包含帧列表,但它们通常表示为与前一帧的差异,以减少数据大小.如果方法中没有帧,这在控制流永远不会加入时发生(即CFG是树),则可以完全省略StackMapTable属性.

因此,这是StackMapTable如何工作以及添加原因的基本思路.最后一个问题是如何创建隐式初始帧.答案当然是在方法的开头,操作数堆栈是空的,局部变量槽具有由方法参数的类型给出的类型,这些类型是从方法描述符确定的.

如果您习惯使用Java,那么方法参数类型在字节码级别的工作方式会有一些细微差别.首先,虚方法有一个隐含的第一个参数.其次,字节码级别不存在布尔,字节,字符和短路.相反,它们都是在幕后实现的.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值