虚拟机栈—动态链接
- 动态链接、方法返回地址、附加信息 :有些地方被称为帧数据区;
- 每一个栈帧内部都包含一个指向运行时常量池中该栈帧所属方法的引用,这个引用的目的就是为了支持当前方法的代码能够实现动态链接(Dynamic Linking),比如:invoke指令;
- Java源文件被编译到字节码文件中时,所有的变量和方法引用都作为符号引用(symbolic Reference)保存在class文件的常量池里。
比如:一个方法调用了另外的其他方法时,就是通过常量池中指向方法的符号引用来表示的,那么动态链接的作用就是为了将这些符号引用转换为调用方法的直接引用(即方法运行所需的的信息存在常量池里面,当方法执行时,需要去常量池里面拿,而拿的方法就是动态链接)。
因为不同的方法,都可能调用常量或者方法,因此在常量池里存储一份,可以节省空间, 而常量池的作用:就是为了提供一些符号和常量,便于指令的识别。
方法返回地址
- 正常执行完成;
- 出现未处理的异常,非正常退出。
无论通过哪种方式退出,在方法退出后都返回到该方法被调用的位置。方法正常退出时,调用者的 pc 计数器的值作为返回地址,即调用该方法的指令的下一条指令的地址;而通过异常退出的,返回地址要通过异常表来确定,栈帧中一般不会保存这部分信息。
- 一个方法在正常调用完成之后,究竟需要使用哪一个返回指令,还需要根据方法返回值的实际数据类型而定;
- 在字节码指令中,返回指令包含ireturn(当返回值是boolean,byte,char,short和int类型时使用),lreturn(Long类型),freturn(Float类型),dreturn(Double类型),areturn。另外还有一个return指令声明为void的方法,实例初始化方法,类和接口的初始化方法使用。
方法执行遇到异常:
- 在方法执行过程中遇到异常(Exception),并且这个异常没有在方法内进行处理,也就是说在本方法的异常表中没有搜索到匹配的异常处理器,就会导致方法退出;
- 方法执行过程中,抛出异常时的异常处理,存储在一个异常处理表中,方便在发生异常的时候找到处理异常的代码;
- 通过异常完成出口退出的不会给他的上层调用者产生任何的返回值。
本质上,方法的退出就是当前栈帧出栈的过程。此时,需要恢复上层方法的局部变量表、操作数栈、将返回值压入调用者栈帧的操作数栈、设置PC寄存器值等,让调用者方法继续执行下去。
一些附加信息
栈帧中还允许携带与Java虚拟机实现相关的一些附加信息。例如:对程序调试提供支持的信息。