细说虚拟机栈

文章出自 

http://www.mynawang.com/

 

引文

    对JVM不了解的请先访问文章《Java虚拟机运行时数据区》,相信会让你大体了解各个内存区域的对应功能。接着,咱们开始细说虚拟机栈     前文中说到:“虚拟机栈是线程私有的,每建立一个线程,虚拟机就会为这个线程建立一个虚拟机栈,虚拟机栈表示Java方法执行的内存模型,每调用一个方法就会为每一个方法生成一个栈帧(Stack Frame),用来存储局部变量表、操做数栈、动态连接、方法出口等信息。每一个方法被调用和完成的过程,都对应一个栈帧从虚拟机栈上入栈和出栈的过程。虚拟机栈的生命周期和线程是相同的”。数据结构

虚拟机栈

    其中,虚拟机栈是一个后入先出的栈。栈帧是保存在虚拟机栈中的,栈帧是用来存储数据和存储部分过程结果的数据结构,同时也被用来处理动态连接(Dynamic Linking)、方法返回值和异常分派(Dispatch Exception)。线程运行过程当中,只有一个栈帧是处于活跃状态,称为“当前活跃栈帧”,当前活动栈帧始终是虚拟机栈的栈顶元素。以下图所示: 栈流程优化

栈帧

    上述内容已对栈帧作了大体介绍,接下去仔细描述栈帧中的操做数栈,动态链接,方法返回地址和一些额外的附加信息。 以下图所示:spa

栈帧详情

1.局部变量表线程

    局部变量表是一组局部变量值存储空间,用于存放方法参数和方法内部定义的局部变量。在Java文件编译为Class文件时,就在方法表的Code属性的max_locals数据项中肯定了该方法须要分配的最大局部变量表的容量。code

2.操做数栈orm

    操做数栈也常被称为操做栈,它是一个后入先出栈。JVM底层字节码指令集是基于栈类型的,全部的操做码都是对操做数栈上的数据进行操做,对于每个方法的调用,JVM会创建一个操做数栈,以供计算使用。和局部变量同样。操做数栈的最大深度也是编译的时候写入到方法表的code属性的max_stacks数据项中。操做数栈的每个元素能够是任意的Java数据类型,包括long、double。32位数据类型所占的栈容量为1,64位数据类型所占的栈容量为2。栈容量的单位为“字宽”,对于32位虚拟机来讲,一个“字宽”占4个字节,64位虚拟机来讲,一个“字宽”占8个字节。当一个方法刚刚执行的时候,这个方法的操做数栈是空的,在方法执行的过程当中,会有各类字节码指向操做数栈中写入和提取值,也就是入栈与出栈操做。例如,在作算术运算的时候就是经过操做数栈来进行的,又或者调用其它方法的时候是经过操做数栈来行参数传递的。 另外,在概念模型中,两个栈帧做为虚拟机栈的元素,相互之间是彻底独立的,可是大多数虚拟机的实现里都会做一些优化处理,令两个栈帧出现一部分重叠。让下栈帧的部分操做数栈与上面栈帧的部分局部变量表重叠在一块儿,这样在进行方法调用返回时就能够共用一部分数据,而无须进行额外的参数复制传递了。生命周期

3.动态链接内存

    每一个栈帧都包含一个指向运行时常量池中该栈帧所属性方法的引用,持有这个引用是为了支持方法调用过程当中的动态链接。在Class文件的常量池中存有大量的符号引用,字节码中的方法调用指令就以常量池中指向方法的符号引用为参数。这些符号引用一部分会在类加载阶段或第一次使用的时候转化为直接引用,这种转化称为静态解析。另一部分将在每一次的运行期期间转化为直接引用,这部分称为动态链接开发

4.方法返回地址get

    当一个方法被执行后,有两种方式退出这个方法。第一种方式是执行引擎遇到任意一个方法返回的字节码指令,这时候可能会有返回值传递给上层的方法调用者(调用当前方法的的方法称为调用者),是否有返回值和返回值的类型将根据遇到何种方法返回指令来决定,这种退出方法方式称为正常完成出口(Normal Method Invocation Completion)。另一种退出方式是,在方法执行过程当中遇到了异常,而且这个异常没有在方法体内获得处理,不管是Java虚拟机内部产生的异常,仍是代码中使用athrow字节码指令产生的异常,只要在本方法的异常表中没有搜索到匹配的异常处理器,就会致使方法退出,这种退出方式称为异常完成出口(Abrupt Method Invocation Completion)。一个方法使用异常完成出口的方式退出,是不会给它的调用都产生任何返回值的。     不管采用何种方式退出,在方法退出以前,都须要返回到方法被调用的位置,程序才能继续执行,方法返回时可能须要在栈帧中保存一些信息,用来帮助恢复它的上层方法的执行状态。通常来讲,方法正常退出时,调用者PC计数器的值就能够做为返回地址,栈帧中极可能会保存这个计数器值。而方法异常退出时,返回地址是要经过异常处理器来肯定的,栈帧中通常不会保存这部分信息。 方法退出的过程实际上等同于把当前栈帧出栈,所以退出时可能执行的操做有:恢复上层方法的局部变量表和操做数栈,把返回值(若是有的话)压入调用都栈帧的操做数栈中,调用PC计数器的值以指向方法调用指令后面的一条指令等。

5.附加信息

    虚拟机规范容许具体的虚拟机实现增长一些规范里没有描述的信息到栈帧中,例如与高度相关的信息,这部分信息彻底取决于具体的虚拟机实现。在实际开发中,通常会把动态链接,方法返回地址与其它附加信息所有归为一类,称为栈帧信息。

相关文章
相关标签/搜索