18.JVM变量槽Slot
1.JVM变量槽Slot的理解
1.Slot
是局部变量表中最基本的存储单元。
2.参数值的存放总是从局部变量表数组的index 0
开始,到数组的-1
的索引结束。
3.局部变量表中存放的是局部变量,包括8
种基本数据类型,引用数据类型,returnAddress
类型的变量。
4.32
位以内的数据占用一个Slot
(包括returnAddress
类型,引用数据类型),64
位类型的(long
, double
)占用两个Slot
。
5.JVM
会为局部变量表中的每一个Slot
分配一个访问索引,通过这个索引来访问局部变量。
6.当一个实例方法(非静态方法)被调用的时候,它的方法参数和方法体内部定义的局部变量将会按照顺序被复制到局部变量的每一个Slot
上。
7.如果需要访问局部变量表中的一个64
位的局部变量值时,只需要使用前一个索引即可。(例如:访问long
或double
类型的变量)
8.如果当前栈帧是由构造方法或者实例方法创建的,那么该对象引用this
将会存放在index
为0
的slot
处,其余的参数按照参数表的顺序继续进行存储。
理解Slot的例子演示:
package jvn; import java.util.Date; public class LocalVariablesTest { private int count = 0; public static void main(String[] args) { LocalVariablesTest test = new LocalVariablesTest(); int num = 10; test.test1(); } //练习: public static void testStatic(){ LocalVariablesTest test = new LocalVariablesTest(); Date date = new Date(); int count = 10; System.out.println(count); //因为this变量不存在于当前方法的局部变量表中!! // System.out.println(this.count); } //关于Slot的使用的理解 public LocalVariablesTest(){ this.count = 1; } public void test1() { Date date = new Date(); String name1 = "atguigu.com"; test2(date, name1); System.out.println(date + name1); } public String test2(Date dateP, String name2) { dateP = null; name2 = "songhongkang"; double weight = 130.5;//占据两个slot char gender = '男'; return dateP + name2; } public void test3() { this.count++; } }
编译上面的java代码,使用Jclasslib
打开生成的LocalVariablesTest.class
文件。关于JClasslib的使用参考:https://blog.csdn.net/u011069294/article/details/107079185
1.选中test1
方法:
从Name
列可以看到总共存储了3个局部变量,this,date
,以及name1
。验证了上面讲到的,当一个方法是构造方法或者实例方法的时候,对象引用this
会被存储到局部变量表的index=0的位置,然后其他的局部变量按顺序存储。
从Index
列可以看出,每个变量的索引的起始位置以及所占的slot
数目。this
索引起始位置是0,它下一个变量data
索引起始位置是1,说明this
占了一个Solt
。同理可以看出data也占了一个Slot
。
2.选中test2
方法:
同样可以看出第一个变量存储的是this
。后面的变量按顺序存储。
特别需要注意的一点的是变量weight
是一个Double
数据类型,索引起始位置是3
,结束位置是5
,所以它占了两个Slot
。
3.选中<init>
方法
可以看到构造方法只存储了一个this
。
9.Slot
是可以重复利用的。如果一个局部变量出了其作用域,那么在其作用域之后声明的新的局部变量就很可能会重复使用过期的局部变量的槽位。SLot
重复利用的例子:
package jvn; public class LocalVariablesTest { public void test4() { int a = 0; { int b = 0; b = a + 1; } //变量c使用之前已经销毁的变量b占据的slot的位置 int c = a + 1; } }
同样使用Jclasslib
打开LocalVariablesTest.class
。
1.选中test4
方法。
可以看出,变量c
和变量b
的索引起始地址都是2
,所以变量c
复用了变量b
的Slot
。