java虚拟机栈 Java  Virtual  Machine  Stacks,线程私有,它的生命周期和线程一致。 线程请求栈深度大于虚拟机所允许的深度,抛出StackOverflowError,栈的大小可以设置,设置大小的

命令是-xss1024(单位可k,m),也可动态扩展,如果动态扩展时,无法申请到足够的内存,抛出outOfMemoryError

           虚拟机栈描述的是 Java方法 执行时的内存模型:每个方法在执行的时候都会创建一个栈帧(stack Frame)。

            栈帧 存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机中入栈出栈的过程。

        1.局部变量表 

           局部变量表存放编译期可知的各种基本数据类型,boolean,byte,char,int,long,float,double,short,对象引用(reference类型,它不等同于对象本身,可能是指向对象起始地址等到引用指针,

也可能是指向一个代表对象的句柄活其他与对象相关的位置),returnAddress类型(指向了一条字节码指令的地址)。

两个局部变量的空间(slot),其余的数据类型只占用1个。局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在帧中分配多大的局部变量空间是

完全确定的,在方法运行期间不会改变局部变量表的大小。

         2.操作数栈

        操作数栈(operand stack)常被称为操作栈,后入先出,最大深度在编译的时候写入到code属性的max_stacks数据项中。

        操作数栈的每一个元素可以是任意的Java数据类型,包括long,double。32位数据类型占用栈容量1,64位占用容量2。在方法执行时,操作数栈深度不会超过在max_stacks数据项中设定的最大值。

        在方法开始执行时,这个方法的操作数栈是空的,在方法执行过程中,会有各种字节码指令往操作数栈中写入和提取内容,即入栈/出栈。

        操作数栈中的元素的数据类型必须和字节码指令的序列严格匹配,编译器编译代码时严格保证,类校验阶段的数据流分析还要再次验证这一点。比如 iadd指令,用于整形数加法,它在执行时,栈顶的两个元素的数据类型必须是int型,不是是long,或者其他类型。

       在概念模型中,两个栈帧作为虚拟机栈的元素,是完全独立的。但在大多虚拟机的实现中都会做一些优化处理,令两个栈帧出现一部分重叠,让下面栈帧的部分操作数栈与上面栈帧的部分局部变量表重叠在一起,这样在进行方法调用是就可以共用一部分数据,无需进行额外的参数复制传递。

        Java虚拟机的解释执行引擎称为“基于栈的执行引擎”,其中所指的“栈”就是操作数栈。

        3.动态链接

       每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接(Dynamic Linking)。

        4.方法返回地址

        一个方法开始执行后,只有两种方式可以退出这个方法。

        第一种是执行引擎遇到任意一个方法返回的字节码指令,这种退出方法的方式被称为正常完成接口(normal method invocation completion)。

       第二种是在方法执行过程中遇见了异常,并且这个异常并没有在方法体内进行处理。只要在本方法的异常表中没有搜索到匹配的异常处理器,就会导致方法退出,这种退出方法的方式称为异常完成出口(abrupt method invocation completion)。

           5.附加信息

         虚拟机规范允许具体的虚拟机实现增加一些规范里没有描述的信息到栈帧中。例如和调试相关的信息,这部分信息完全取决于具体的虚拟机实现。在实际开发中,一般把动态链接、方法返回地址、附加信息全部归为一类,称为栈帧信息。