JVM规范学习:invokeinterface
2014-08-11 21:27
190 查看
本文翻译自: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。
假设C为objectref的类型,实际调用的方法按照下列过程查找。
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 如果方法有返回值,则该平台相关的返回值按照平台相关的实现方式转换成该方法的返回类型,并压入操作数栈。
链接异常
接口方法的符号引用解析期间,任何和接口方法解析相关的异常都可能被抛出。
运行时异常
如果objectref为null,则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个的局部变量位置。
Invokeinterface
操作
调用接口方法
格式
invokeinterface
indexbyte1
indexbyte2
count
0
编码
invokeinterface = 185 (0xb9)
操作数栈
..., objectref, [arg1, [arg2 ...]] →
描述
无符号indexbyte1andindexbyte2用来构造一个指向当前类的运行时常量池索引,索引值通过(indexbyte1 << 8) |indexbyte2.构造得出。运行时常量池在该索引的位置必须为一个接口方法的符号引用,该符号引用给出了该接口方法的名称和描述以及包含该接口方法的接口的符号引用。该接口方法被解析,解析到的方法不能为实例,类或者接口初始化方法。
count操作数为无符号字节,不能为0。Objectref必须为引用类型,在操作数栈中nargs个参数值必须紧跟在objectref后面。这些参数的个数,类型和顺序必须和接口方法的描述一致。第三个运算元必须为0。
假设C为objectref的类型,实际调用的方法按照下列过程查找。
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 如果方法有返回值,则该平台相关的返回值按照平台相关的实现方式转换成该方法的返回类型,并压入操作数栈。
链接异常
接口方法的符号引用解析期间,任何和接口方法解析相关的异常都可能被抛出。
运行时异常
如果objectref为null,则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个的局部变量位置。
相关文章推荐
- JVM规范学习:invokevirtual
- JVM规范学习:invokespecial
- JVM学习笔记二:内存结构规范
- Java存储结构-JVM规范学习笔记
- JVM规范学习:invokedynamic
- JVM规范学习:invokestatic
- JVM指令之invokestatic,invokespecial,invokeinterface,invokevirtual,invokedynamic
- JVM规范学习:签名多态性
- java反射机制学习笔记与Method类invoke方法jvm底层优化方案
- Atlas学习手记(29):JavaScript面向对象的扩展(三):接口Interface
- 开发规范学习心得
- Java 学习笔记 (1) -Java 编程规范 环境变量
- boost 学习笔记:regex语法规范(翻译)
- 操作系统学习常见疑惑问与答[接口规范部分]—问题1-4 http://blog.csdn.net/yxin1322/archive/2006/04/04/650898.aspx
- B/S软件开发测试规范_试行1.1.0604 (收录于网络,供学习用,如果侵犯了你们版权请与本人联系)
- JVM 类文件 类装入器 初级概念学习
- Java 学习笔记 (3) -抽象类 abstract 接口 interface 内部类 inner class 继承 extends 实现 implements 包 package
- 接口学习心得(Interface)
- Yahoo! User Interface Library,YUI,YUI下载,YUI学习,YUI是什么,YUI浅谈,YUI研究(1)
- JAVA语言规范学习笔记(3)