JVM栈帧内部结构-局部变量表
栈帧内部结构:
1) 局部变量表(Local Variables)
2) 操作数栈(Operand Stack)或表达式栈
3) 动态链接(Dynamic Linking)或指向运行时常量池的方法引用
4) 方法返回地址(Return Address)或方法正常退出或异常退出的定义
5) 一些附加信息
局部变量表(Local Variables):
局部变量表被称之为局部变量数组或本地变量表。
定义为一个数字数组,主要用于存储方法参数和定义在方法体内的局部变量,这些数据类型包括各类基本数据类型,对象引用(Reference)以及Return Address类型。
由于局部变量表是建立在线程的栈上,是线程私有的数据,因此不存在数据安全问题。
局部变量表所需的容量大小是在编译器确定下来的,并保存在方法Code属性的Maximum local variables数据项中,在方法运行期间是不会改变局部变量表的大小。
方法嵌套调用的次数由栈的大小决定,栈越大方法调用的次数越多。
局部变量表中的变量只在当前方法调用中有效,在执行方法时,虚拟机通过使用局部变量表完成参数值到参数变量列表的传递过程,当前方法调用结束后,随着方法栈帧的销毁,局部变量表也随之销毁。
Slot(槽)的理解:
参数值的存放是在局部变量数组的index 0开始的,到数组长度-1的索引结束。
局部变量表的基本存储单猥是Slot(变量槽)。
局部变量表中存放编译器可知的各种基本数据类型(8种),引用类型(reference),Return Address类型的变量。
在局部变量表中,32位以内的类型占用一个Slot(包括Return Address类型),64位类型(long和double)占用两个Slot
1) byte,short,char在存储前被转换位int,boolean也被转换位int(0表示false,非0表示true)。
2) long和double占据两个Slot
Java会位局部变量表中的每一个Slot都会分配一个访问索引,通过这个索引可以访问到局部变量表中指定的局部变量值。
当一个实例方法被调用的时候,它的方法参数和方法体内部的局部变量将会按照顺序被复制到局部变量表中的每一个Slot上
如果需要访问局部变量表的一个64bit的局部变量值时,只需要使用前一个索引即可。
如果当前方法是由构造方法或实例方法创建的(非静态方法),那么该对象引用this将会存放在index为0的Slot处,其余参数按照参数表顺序继续排列。
Slot的重复利用:
栈帧的局部变量表中的槽位是可以重用的,如果一个局部变量过了其作用域,那么在其作用域之后申明新的局部变量就很有可能会重复用过期局部变量的槽位,达到节省资源的目的。
静态变量与局部变量对比:
变量分类(按数据类型区分):1) 基本数据类型 2) 引用数据类型
在类中声明位置区分:
1) 成员变量:在使用前,都经历过默认初始化赋值,
类变量:在链接(Linking)的准备(Prepare)阶段,给类变量默认赋值,初始化(initialization)阶段给类变量显式赋值,即静态代码块赋值。
2) 局部变量:在使用前,必须进行显式赋值,否则编译不通过。
局部变量表与GC垃圾回收关系:
在方法执行时,虚拟机使用局部变量表完成方法的传递。
局部变量表中的变量也是重要的垃圾回收根节点,只要被局部变量表中直接或间接引用的对象都不会被回收。