局部变量表中的一些小细节

87 阅读3分钟

1.操作数栈

局部变量表指的是在虚拟机栈部分的组成元素。虚拟机栈中的四个主要的元素分别是,局部变量表,操作数栈,动态链接,返回地址。
操作数栈指的是,在方法执行的过程中,不断在这个操作数栈中进行入栈,出栈操作,完成变量的运算的操作。在这个里面涉及到一个称为栈深度的一个变量。其中32bit的变量占据一个栈深度,64bit的变量占据两个栈深度。同时这个操作数栈并不是真实的栈结构。而是用数组完成的栈操作。

2.动态链接

这个东西就是指向运行时常量池的对象的引用。主要是方便在方法内调用其他的方法的时候,具体需要调用的实际方法到底是哪一个。这个是通过动态链接来确定的。

3.返回地址

这个返回地址存储的是调用这个方法的PC寄存器的值,主要是用来当这个方法结束的时候回到调用方法的位置继续执行。

4.局部变量表

在局部变量表中,也是以数组的形式进行存储的。其中存储的基本单位是slot,槽。32bit的数据占据1个slot。64位占据2个slot。在局部变量表中存储的变量包括,形参,以及方法体内部定义的参数。需要注意的是如果这个方法是一个成员方法,那么这个局部变量表的第一个位置是this。静态方法的话,没有this。局部变量表存储的内容是,这个局部变量在当前方法中起作用的范围。例如在第3行开始到第29行失效。

局部变量表需要强调的几点

  • 局部变量表的槽是可以复用的。因为有的局部变量可能是在一个代码块内部,当这个运行到这个代码块以外的时候,这个变量就会被销毁。因此为了节约空间,采用了复用的思路处理。
String test4(){
   {
       int a = 10;
       System.out.println(a);
   }
   int b = 20;
   return null;
}

WX20240803-163949@2x.png 可以通过看上面的这一张局部变量表,其中槽位为0的位置被this占据。而槽位为1的位置被变量a,b同时占据。

特别特别注意的一点是,如果没有一个 b 去覆盖变量a的位置(此时a存放在堆空间,创建一个对象即可)

String test4(){
    {
        Object o = new Object();
    }

    return null;
}

这个时候,局部变量表仅仅只有一个this出现,而通过看杂项这一项的时候,发现局部变量表的槽位是2.这也就表示这个堆空间没有被释放掉。这种情况就会导致内存泄漏的风险。解决方案是,及时用一个变量去覆盖填充。