16.JVM栈帧内部结构-局部变量表
1.局部变量表(Local variables)
1.局部变量表也称为局部变量数组或本地变量表。
2.局部变量表定义为一个数字数组,主要用于存储方法参数和定义在方法体内的局部变量。(局部变量表的作用)
3.局部变量表示栈帧中的数据,栈帧被线程私有,所以不存在线程安全的问题,也就是多线程之间不会相互影响。
4.局部变量表的大小在编译时期确定。一旦确定,就不会再改变。
查看局部变量表:将下面的java代码产生的class文件使用javap进行反编译。
public class LocalVariablesTest { public static void main(String[] args) { LocalVariablesTest test = new LocalVariablesTest(); int num = 10; } }
找到生成的LocalVariablesTest.class文件,使用javap -v LocalVariablesTest
, 输出如下,最下面有一个LocalVariableTable
就是局部变量表。
可以看到局部变量表存储了三个变量,分别为args,test,num。并且都有大小solt。总共加起来的solt是3。这里就可以看出来,局部变量表的大小是在编译器确定的。因为我们只是反编译了class文件,就能够看到局部变量表以及它的大小。
D:\Eclipse_workspace\JVM\jvn\bin\jvn>javap -v LocalVariablesTest Classfile /D:/Eclipse_workspace/JVM/jvn/bin/jvn/LocalVariablesTest.class Last modified 2020-7-1; size 466 bytes MD5 checksum 24673853d3865f4d8d0bab8ca5b3435b Compiled from "LocalVariablesTest.java" public class jvn.LocalVariablesTest minor version: 0 major version: 52 flags: ACC_PUBLIC, ACC_SUPER Constant pool: #1 = Class #2 // jvn/LocalVariablesTest #2 = Utf8 jvn/LocalVariablesTest #3 = Class #4 // java/lang/Object #4 = Utf8 java/lang/Object #5 = Utf8 <init> #6 = Utf8 ()V #7 = Utf8 Code #8 = Methodref #3.#9 // java/lang/Object."<init>":()V #9 = NameAndType #5:#6 // "<init>":()V #10 = Utf8 LineNumberTable #11 = Utf8 LocalVariableTable #12 = Utf8 this #13 = Utf8 Ljvn/LocalVariablesTest; #14 = Utf8 main #15 = Utf8 ([Ljava/lang/String;)V #16 = Methodref #1.#9 // jvn/LocalVariablesTest."<init>":()V #17 = Utf8 args #18 = Utf8 [Ljava/lang/String; #19 = Utf8 test #20 = Utf8 num #21 = Utf8 I #22 = Utf8 SourceFile #23 = Utf8 LocalVariablesTest.java { public jvn.LocalVariablesTest(); descriptor: ()V flags: ACC_PUBLIC Code: stack=1, locals=1, args_size=1 0: aload_0 1: invokespecial #8 // Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 3: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this Ljvn/LocalVariablesTest; public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V flags: ACC_PUBLIC, ACC_STATIC Code: stack=2, locals=3, args_size=1 0: new #1 // class jvn/LocalVariablesTest 3: dup 4: invokespecial #16 // Method "<init>":()V 7: astore_1 8: bipush 10 10: istore_2 11: return LineNumberTable: line 5: 0 line 6: 8 line 7: 11 LocalVariableTable: // 局部变量表,可以看到局部变量表存储了三个变量,分别为args,test,num。并且都有大小solt。总共加起来的solt是3。这里就可以看出来,局部变量表的大小是在编译器确定的。因为我们只是反编译了class文件,就能够看到局部变量表以及它的大小。 Start Length Slot Name Signature 0 12 0 args [Ljava/lang/String; 8 4 1 test Ljvn/LocalVariablesTest; 11 1 2 num I } SourceFile: "LocalVariablesTest.java"
5.方法嵌套调用的次数有栈的大小决定。栈越大,方法嵌套调用的次数越多。一个方法,参数和局部变量越多,栈帧就越大,函数调用占用的栈空间就越大,其能够嵌套调用的次数就越少。
6.局部变量表中的变量只在当前方法中有效。当方法调用结束后,随着方法栈帧的销毁,局部变量表也会随之销毁。
局部变量表补充说明:
1.在栈帧中,与性能调优关系最为密切的部分就是前面提到的局部变量表。在方法执行时,虚拟机使用局部变量表完成方法的传递。
2.局部变量表中的变量也是重要的垃圾回收根节点,只要被局部变量表中直接或间接引用的对象都不会被回收。