JVM_栈
内存中的栈与堆
栈是运行时的单位,而堆是存储的单位
即∶栈解决程序的运行问题,即程序如何执行,或者说如何处理数据。堆解决的 是数据存储的问题,即数据怎么放、放在哪儿。
栈中可能出现的异常
Java 虚拟机规范允许Java栈的大小是动态的或者是固定不变的。
>如果采用固定大小的Java虚拟机栈,那每一个线程的Java虚拟机栈容量可以在线程创建的时候独立选定。如果线程请求分配的栈容量超过Java 虚拟机栈允许的最大容量,Java虚拟机将会抛出一个StackOverflowError 异常。
>如果Java虚拟机栈可以动态扩展,并且在尝试扩展的时候无法中请到足够的内存,或者在创建新的线程时没有足够的内存去创建对应的虚拟机栈,虚拟机将会抛出一个OpOfMempryError异常。
栈中存储什么?
每个线程都有自己的栈,栈中的数据都是以栈帧(stack Frame)的格式存在。
在这个线程上正在执行的每个方法都各自对应一个栈帧(Stack Frame)。
栈帧是一个内存区块,是一个数据集,维系着方法执行过程中的各种数据信息。
栈运行原理
不同线程中所包含的栈帧是不允许存在相互引用的,即不可能在一个栈帧之中引用另外一个线程的栈帧。
如果当前方法调用了其他方法,方法返回之际,当前栈帧会传回此方法的执行结果给前一个栈帧,接着,虚拟机会丢弃当前栈帧,使得前一个栈帧重新成为当前栈帧。
Java方法有两种返回函数的方式,一种是正常的函数返回,使用return指令;另外一种是抛出异常。不管使用哪种方式,都会导致栈帧被弹出。

局部变量表(local variables)
局部变量表也被称之为局部变量数组或本地变量表。
·定义为一个数字数组,主要用于存储方法参数和定义在方法体内的局部变量,这些数据类型包括各类基本数据类型、对象引用(reference),以及returnAddress类型。
·由于局部变量表是建立在线程的栈上,是线程的私有数据,因此不存在数据安全问题。
·局部变量表所需的容量大小是在编译期确定下来的,并保存在方法的Code属性的maximum local variables数据项中。在方法运行期间是不会改变局部变量表的大小的。
举例∶静态变量与局邹变量的对比
成员变量: 类变量:参数表分配完毕之后,再根据方法体内定义的变量的顺序和作用域分配。
我们知道类变量表有两次初始化的机会,第一次是在"准备阶段",执行系统初始化,对类变量设置零值,另一次则是在"初始化"阶段,赋予程序员在代码中定义的初始值。
实例变量:随着对象的创建,会在对空间中分配实例变量空间。并进行默认赋值
局部变量:和类变量初始化不同的是,局部变量表不存在系统初始化的过程,这意味着一旦定义了局部变量则必须人为的初始化,否则无法使用。
public void test(){ int i; System.out.println(i); }
这样的代码是错误的,没有赋值不能够使用。
操作数栈
· 操作数栈,主要用于保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间。
· 操作数栈就是JVM执行引擎的一个工作区,当一个方法刚开始执行的时候,一个新的栈帧也会随之被创建出来,这个方法的操作数栈是空的。
·每一个操作数栈都会拥有一个明确的栈深度用于存储数值,其所需的最大深度在编译期就定义好了,保存在方法的Code属性中,为max stack的值。
· 栈中的任何一个元素都是可以任意的Java数据类型。
32bit的类型占用一个栈单位深度
64bit的类型占用两个栈单位深度
·操作数栈并非采用访问索引的方式来进行数据访问的,而是只能通过标准的入栈(push)和出栈(pop)操作来完成一次数据访问。

浙公网安备 33010602011771号