JVM规范学习:invokeinterface

本文翻译自:http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.invokeinterface

Invokeinterface

操作

调用接口方法

格式

invokeinterface
indexbyte1
indexbyte2
count
0

编码

invokeinterface = 185 (0xb9)

操作数栈

..., objectref, [arg1, [arg2 ...]] →

 

描述

无符号indexbyte1andindexbyte2用来构造一个指向当前类的运行时常量池索引,索引值通过(indexbyte1 << 8) |indexbyte2.构造得出。运行时常量池在该索引的位置必须为一个接口方法的符号引用,该符号引用给出了该接口方法的名称和描述以及包含该接口方法的接口的符号引用。该接口方法被解析,解析到的方法不能为实例,类或者接口初始化方法。

count操作数为无符号字节,不能为0。Objectref必须为引用类型,在操作数栈中nargs个参数值必须紧跟在objectref后面。这些参数的个数,类型和顺序必须和接口方法的描述一致。第三个运算元必须为0

假设Cobjectref的类型,实际调用的方法按照下列过程查找。

l        如果C包含一个和要解析的方法名称及描述符一样的方法声明,则该声明即为要调用的方法,查找结束。

l        否则,如果C有父类,则在其父类及父类的父类中递归执行第一步中的查找。

l        如果还未找到,则抛出AbstractMethodError错误。

 

如果方法是同步方法(synchronized),则在与objetref关联的监视器上执行enter或reenter操作,就像在当前线程中执行monitorenter指令一样。

如果方法不是native的,nargs个参数和objectref从操作数栈中弹出,在JVM栈中为该调用方法创建一个新的栈帧,objectref和nargs个参数相继作为新栈帧的局部变量存入。Objectref存入第一个局部变量(slot0),arg1存入第二个(slot1)(如果arg0为long或者double类型,则存入slot1和slot2)等等。

任何float类型的变量在存入局部变量表之前都会先进行值集转换。新栈帧成为当前栈帧,JVM PC设置为新方法的第一条指令操作码,程序执行从该方法第一条指令继续。

 如果该方法是native的,并且平台相关的实现代码尚未绑定到当前JVM,就这样(译者:不再绑定?)。nargs个参数和objectref从操作数栈中弹出,作为参数依次传递给实现代码作为局部变量。任何float类型的变量在存入局部变量表之前都会先进行值集转换。参数的传递和代码执行方式依赖于具体的实现方式,当方法返回时,发生如下情形:

 

l        如果native方法是同步的(synchronized),则和objectref关联的监视器被更新并可能退出,就像在当前线程中执行monitorexit指令一样。

l        如果方法有返回值,则该平台相关的返回值按照平台相关的实现方式转换成该方法的返回类型,并压入操作数栈。

 

链接异常

接口方法的符号引用解析期间,任何和接口方法解析相关的异常都可能被抛出。

运行时异常

如果objectrefnull,则invokeinterface指令抛出NullPointerException异常。

如果objectref所属类没有实现解析出的接口,则invokeinterface指令抛出IncompatibleClassChangeError错误。

如果没有选择任何与解析出的name和描述符匹配的方法,则invokeinterface指令抛出AbstractMethodError错误。

如果选择的方法不是public的,则invokeinterface指令抛出IllegalAccessError错误。

如果选择的方法是abstract的,则invokeinterface指令抛出AbstractMethodError错误。

如果选择的方法是native的,但平台相关的实现代码无法绑定到当前JVM,则invokeinterface指令抛出UnsatisfiedLinkError错误。

 

备注

     count记录了参数的个数,一个long或者double类型的参数记2,其余的参数记1,这个信息也可以从解析出的方法描述符中得到,放在这里是由于历史原因。

第四个运算字节的存在是为额外的运算元预留空间,这些运算元用于某些oracle的java虚拟机,用来在运行时用某些专用的伪指令替换invokeinterface指令。因此必须保留以达到后项兼容性。

nargs个参数并不一定就对应nargs个局部变量,对于long或double类型的参数值就需要连续两个局部变量的位置来存储,这时,nargs个参数的传递就需要多于nargs个的局部变量位置。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值