【转帖】16.JVM栈帧内部结构-局部变量表

济南小老虎 / 2024-01-09 / 原文

1.局部变量表(Local variables)

1.局部变量表也称为局部变量数组或本地变量表。
2.局部变量表定义为一个数字数组,主要用于存储方法参数和定义在方法体内的局部变量。(局部变量表的作用)
3.局部变量表示栈帧中的数据,栈帧被线程私有,所以不存在线程安全的问题,也就是多线程之间不会相互影响。(这里并不是绝对的,其实有可能出现线程安全问题,参考https://blog.csdn.net/u011069294/article/details/107157140)
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.局部变量表中的变量也是重要的垃圾回收根节点,只要被局部变量表中直接或间接引用的对象都不会被回收。
      在这里插入图片描述

      更多JVM文章请参考我的JVM专栏:https://blog.csdn.net/u011069294/category_10113093.html

      文章知识点与官方知识档案匹配,可进一步学习相关知识
      Java技能树Java中的变量与常量变量的定义118285 人正在系统学习中