局部变量表
局部变量表(Local Variables Table
)是一组变量值的存储空间,用于存放方法参数和方法
内部定义的局部变量。在Java
程序被编译为Class
文件时,就在方法的Code
属性的max_locals
数据项中确定了该方法所需要分配的局部变量表的最大容量。
局部变量表的容量以变量槽(Variable Slot
)为最小单位,《Java
虚拟机规范》中并没有明确
指出一个变量槽应占用的内存空间大小,只是很有引导性地说到每个变量槽都应该能存放一个
boolean
、byte
、char
、short
、int
、float
、reference
或returnAddress
类型的数据。
reference
类型表示对一个对象实例的引用,至少能通过这个引用做到两件事情,一是从根据引用
直接或间接地查找到对象在Java
堆中的数据存放的起始地址或索引,二是根据引用直接或间接地
查找到对象所属数据类型在方法区中存储的类型信息。
returnAddress
类型目前很少见,它是为字节码指令jsr
、jsr_w
和ret
服务的,指向一条字节码
指令的地址,某些很古老的Java
虚拟机使用这几条指令来实现异常处理时的跳转,现在完全改为
采用异常表来代替了。
Java
虚拟机通过索引定位的方式使用局部变量表,索引值的范围从0开始至局部变量表最大的变量槽数量。
如果访问的是32位数据类型的变量,索引N
就代表使用第N
个变量槽,如果访问的是64位数据类型的变量,
则会同时使用第N
和N+1
两个变量槽。
当一个方法被调用时,Java
虚拟机会使用局部变量表来完成参数值到参数变量列表的传递过程,即实参到
形参的传递。如果执行的是实例方法那局部变量表第0位索引的变量槽默认是用于传递方法所属对象实例的
引用,在方法中可以通过this
来访问到这个隐含的参数。其余参数则按照参数表顺序排列,再根据方法体
内部定义的变量顺序和作用域分配其余的变量槽。
为了尽可能节省栈桢耗用的内存空间,局部变量表中的变量槽是可以重用的,方法体中定义的变量,其作用
域并不一定会覆盖整个方法体,如果当前字节码PC计数器的值已经超出了某个变量的作用域,那这个变量
对应的变量槽就可以交给其他变量来重用。不过某些情况下,变量槽的复用会直接影响垃圾收集行为。
关于局部变量表,还有一点可能会对实际开发产生影响,就是局部变量不像类变量那样存在“准备阶段”,
因此没有为类变量赋值没有关系,类变量仍具有一个确定的初始值。但局部变量不一样,如果一个局部变量
定义了但没有赋初始值,那它是完全不能使用的。编译器在编译期间能检测到并提示这一点。
public static void main(Strin[] args) {
int a;
System.out.println(a);
}