每个栈帧中包含:

  • 局部变量表(Local Variables)
  • 操作数栈(Opreand Stack) 或表达式栈
  • 动态链接 (Dynamic Linking) (或指向运行时常量的方法引用)
  • 动态返回地址(Return Address) (或方法正常退出或者异常退出的引用的定义)
  • 一些附加信息

局部变量表

  • 局部变量表也被称之为局部变量数据组或本地变量表
  • 定义为一个数字数组,主要用户存储方法参数和定义在方法体内的局部变量,这些数据类型包括各类基本数据类型、对象引用(reference),以及returnAddress 类型
  • 由于局部变量表示建立在线程的栈上,是线程的私有数据,因此不存在数据安全问题
  • 局部变量表所需要的容量大小是在编译期确定下来的,并保存在方法的Code属性的maximun local variables数据项中,在方法运行期间时不会改变局部变量表的大小的
  • 方法嵌套调用的次数由栈的大小决定,一般来说,栈越大,方法嵌套调用次数越多,对于一个函数而言,他的参数和局部变量越多,使得局部变量表膨胀,它的栈就越大,以满足方法调用所需传递的信息增大的需求,进而函数调用就会占更多的栈空间,导致其嵌套调用次数就会减少
  • 局部变量表中的变量只在当前方法调用中有效。在方法执行时,虚拟机通过使用局部变量表完成参数值到参数变量列表的传递过程,当方法调用结束后,随着方法栈的销毁,局部变量表也会随之销毁

局部变量表的存储单元Slot(变量槽)

  • 参数值的存放总是在局部变量数据的index0开始,到数组长度-1的索引结束
  • 局部变量表,最基本的存储单元是Slot(变量槽)
  • 局部变量表中存放编译期可知的各种基本数据类型(8种)、引用类型(reference)、returnAdderss类型的变量
  • 在局部变量表中,32位以内的类型只占一个slot(包括returnAdderss类型)64位的类型(long和double)占用两个slot

    • byte、short、char在存储前被转换为int,boolean也被准换为int,0为false,1为true
    • long和double则占据两个slot
  • JVM会为局部变量表中的每一个slot都分配一个访问索引,通过这个索引即可成功的访问到局部变量表中指定的局部变量值
  • 当一个实例方法被调用的时候,它的方法参数和方法体内部定义的局部变量表将会按照顺序被复制到局部变量表中的每一个slot上
  • 如果需要访问局部变量表中一个64bit的局部变量值时,只需要使用前一个索引即可
  • 如果当前帧是由构造方法或者实例方法创建的,那么该对象引用this将会被存放在index为0的slot处,其余的参数按照参数表顺序继续排列

各个类型占用slot图示

  • slot也是可以进行重复利用的,即如果一个局部变量过了其作用域,那么在其作用域之后申明的新的局部变量就很有可能会复用过期的局部变量的槽位,从而达到节约资源的目的。主要的运用方式如下所示,其中{}外作用域就结束了
    //出了大括号就不能用了
public void LocalVar(){
{
int a= 0;
System.out.println(a);
}
//此时b就会复用a的槽位
int b=0;
}

常见问题

Q:为什么static中不能调用this方法

A:因为this的索引只存在构造方法和实例方法的局部变量表中,而static是在初始化方法<clinit>中进行初始化的,里面没有保存this变量的索引

Q:变量的分类

A:

    • 按照数据类型分类

      • 基本数据类型
      • 引用数据类型(对象)
    • 按照在类中的位置分类
      • 成员变量:类中变量,在使用前,都经历默认初始化赋值

        • 类变量,Linking的prepare阶段,给类变量默认赋值–>initial阶段,给类变量显示赋值,即静态代码块赋值
        • 实例变量,随着对象的创建,会在堆空间中分配实例变量空间,并进行默认赋值
      • 局部变量:方法中的变量。在使用时必须进行显示的赋值,否则编译不通过

Q:局部变量与成员变量的对比

A:

    • 参数表分配完毕以后,在根据方法体内定义的变量的顺序和作用域分配
    • 我们知道类变量表有两次初始化的机会,第一次是在“准备阶段”,执行系统初始化,对类变量设置零值,另一次是在“初始化”阶段,赋予变量在代码中定义的初始值
    • 和类变量初始化不同的是,局部变量表不存在系统初始化过程中,这就意味着一旦定了局部变量则必须认为的初始化,否则无法使用
public void test(){
int i;
Systme.out.println(i);
//这种是编译不通过的
}

其他

  • 在栈帧中,与性能调优关系最为密切的部分就是前面提到的局部变量表,在方法执行时,虚拟机使用局部变量表完成方法的传递
  • 局部变量表中的变量也是重要的垃圾回收根节点,只要被局部变量表中的直接或者间接引用的对象都不会被回收
  • 也可以新建局部对象

附:JVM学习目录

栈帧的内部结构--局部变量表(Local Variables)的更多相关文章

  1. 栈帧的内部结构--操作数栈(Opreand Stack)

    每个栈帧中包含: 局部变量表(Local Variables) 操作数栈(Opreand Stack) 或表达式栈 动态链接 (Dynamic Linking) (或指向运行时常量的方法引用) 动态返 ...

  2. 栈帧的内部结构--动态链接 (Dynamic Linking)

    每个栈帧中包含: 局部变量表(Local Variables) 操作数栈(Opreand Stack) 或表达式栈 动态链接 (Dynamic Linking) (或指向运行时常量的方法引用) 动态返 ...

  3. 栈帧的内部结构--动态返回地址(Return Address)

    每个栈帧中包含: 局部变量表(Local Variables) 操作数栈(Opreand Stack) 或表达式栈 动态链接 (Dynamic Linking) (或指向运行时常量的方法引用) 动态返 ...

  4. JVM-栈帧之局部变量表

    1.栈帧的内部结构 每个栈帧中存储着: 局部变量表(Local Variables) 操作数栈(Operand Stack)(或表达式栈) 动态链接(Dynamic Linking)(或指向运行时常量 ...

  5. 从 i++ 和 ++i 说起局部变量表和操作数栈

    本文转载自:从 i++ 和 ++i 说起局部变量表和操作数栈 最近公司有人看了尚硅谷柴林燕老师的第一季面试题,就想来考考我.我觉得柴老师讲的很好,部分内容可以延伸一下,所以写这篇文章分享给大家! 这篇 ...

  6. Java虚拟机栈--栈帧

    栈帧的内部结构 每个栈帧中存储着 1.局部变量表(Local Variables) 2.操作数栈(Operand Stack)(或表达式栈) 3.动态链接(Dynamic Linking)(或执行&q ...

  7. 2.Jvm 虚拟机栈和栈帧

    Jvm 虚拟机栈和栈帧 1.栈帧(frames) 官网描述 A frame is used to store data and partial results, as well as to perfo ...

  8. 详细解析Java虚拟机的栈帧结构

    欢迎关注微信公众号:万猫学社,每周一分享Java技术干货. 什么是栈帧? 正如大家所了解的,Java虚拟机的内存区域被划分为程序计数器.虚拟机栈.本地方法栈.堆和方法区.(什么?你还不知道,赶紧去看看 ...

  9. 深入理解java虚拟机(十) Java 虚拟机运行时栈帧结构

    运行时栈帧结构 栈帧(Stack Frame) 是用于虚拟机执行时方法调用和方法执行时的数据结构,它是虚拟栈数据区的组成元素.每一个方法从调用到方法返回都对应着一个栈帧入栈出栈的过程. 每一个栈帧在编 ...

随机推荐

  1. Locust性能测试3--参数化、数据依赖

    场景链路压测的时候通常都是按照用户实际使用流程进行压测,同接口自动化一样,一定会涉及到数据依赖的问题 1.举例 Django后台通常需要csrf验证,而一般csrftoken需要通过get接口获得 f ...

  2. Shell编程—sed进阶

    1多行命令 sed编辑器包含了三个可用来处理多行文本的特殊命令. N:将数据流中的下一行加进来创建一个多行组来处理. D:删除多行组中的一行. P:打印多行组中的一行. 1.1next命令 1. 单行 ...

  3. Redis主从复制(读写分离)

    主从复制(读写分离):读在从库读,写在主库写. 主从复制的好处:避免redis单点故障构建读写分离架构,满足读多写少的需求. 主从架构: 操作(启动实例,在一台机器上启动不同的实例,进行伪主从复制): ...

  4. 第3关-input()函数

    第3关-input()函数 一.input()函数 import time print('亲爱的同学:') time.sleep(1) print('我们愉快地通知您,您已获准在霍格沃茨魔法学校就读. ...

  5. Java二进制和位运算,这一万字准能喂饱你

    基础不牢,地动山摇.本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以免费学习.关注公众号[BAT的乌托 ...

  6. 消息型中间件之RabbitMQ集群

    在上一篇博客中我们简单的介绍了下rabbitmq简介,安装配置相关指令的说明以及rabbitmqctl的相关子命令的说明:回顾请参考https://www.cnblogs.com/qiuhom-187 ...

  7. 从零开始的SpringBoot项目 ( 三 ) 项目打包( war包篇 )

    pom.xml 修改打包类型 jar 改为 war 添加 tomcat 依赖 找到最右边的 Maven Projects,点击进去,选择需要打包的项目,并点击 install,就开始打包了,打包前先点 ...

  8. istio的安全(概念)

    Istio 安全(概念) 目录 Istio 安全(概念) 高层架构 Istio身份 身份和证书管理 认证 Mutial TLS认证 宽容(Permissive)模式 安全命名 认证架构 认证策略 策略 ...

  9. Nodejs模块:path

    当前版本:v 10.16.0 一,获取文件相关信息 1,path.basename(filepath[, ext]) 获取该文件的文件名,如果有扩展名,则一起显示扩展名: 如果不想展示扩展名,只想展示 ...

  10. 痞子衡嵌入式:导致串行NOR Flash在i.MXRT下无法正常下载/启动的常见因素之SFDP

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是导致串行NOR Flash在i.MXRT下无法正常下载/启动的常见因素之SFDP. i.MXRT系列MCU发布已两年多了,基于i.MXR ...