【jvm】虚拟机栈之局部变量表

news2025/1/18 7:01:54

目录

        • 一、说明
        • 二、代码分析
          • 2.1 代码示例
          • 2.2 执行javap
          • 2.3 jclasslib插件查看
        • 三、对slot的理解
          • 3.1 说明
          • 3.2 slot索引图
          • 3.3 实例方法的局部变量表
          • 3.4 long和double类型变量占2个slot
        • 四、slot的重复利用
          • 4.1 说明
          • 4.2 变量c复用变量b的槽位
        • 五、静态变量与局部变量对比

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

/**
 * @Author wangyouhui
 * @Description 局部变量表测试
 **/
public class LocalVariableTest {
    public static void main(String[] args) {
        LocalVariableTest localVariableTest = new LocalVariableTest();
        int num = 10;
        localVariableTest.print();
    }

    private void print() {
        System.out.println("局部变量表");
    }
}
2.2 执行javap
  • 1.执行javap -v StackOverflowErrorLearning.class
Classfile /F:/jdk-learning/jvm/target/classes/com/learning/stack/local_variables/LocalVariableTest.class
  Last modified 2023-10-16; size 785 bytes
  MD5 checksum e16aaaceec49515090d5cb15e4c6467a
  Compiled from "LocalVariableTest.java"
public class com.learning.stack.local_variables.LocalVariableTest
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #8.#26         // java/lang/Object."<init>":()V
   #2 = Class              #27            // com/learning/stack/local_variables/LocalVariableTest
   #3 = Methodref          #2.#26         // com/learning/stack/local_variables/LocalVariableTest."<init>":()V
   #4 = Methodref          #2.#28         // com/learning/stack/local_variables/LocalVariableTest.print:()V
   #5 = Fieldref           #29.#30        // java/lang/System.out:Ljava/io/PrintStream;
   #6 = String             #31            // 局部变量表
   #7 = Methodref          #32.#33        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #8 = Class              #34            // java/lang/Object
   #9 = Utf8               <init>
  #10 = Utf8               ()V
  #11 = Utf8               Code
  #12 = Utf8               LineNumberTable
  #13 = Utf8               LocalVariableTable
  #14 = Utf8               this
  #15 = Utf8               Lcom/learning/stack/local_variables/LocalVariableTest;
  #16 = Utf8               main
  #17 = Utf8               ([Ljava/lang/String;)V
  #18 = Utf8               args
  #19 = Utf8               [Ljava/lang/String;
  #20 = Utf8               localVariableTest
  #21 = Utf8               num
  #22 = Utf8               I
  #23 = Utf8               print
  #24 = Utf8               SourceFile
  #25 = Utf8               LocalVariableTest.java
  #26 = NameAndType        #9:#10         // "<init>":()V
  #27 = Utf8               com/learning/stack/local_variables/LocalVariableTest
  #28 = NameAndType        #23:#10        // print:()V
  #29 = Class              #35            // java/lang/System
  #30 = NameAndType        #36:#37        // out:Ljava/io/PrintStream;
  #31 = Utf8               局部变量表
  #32 = Class              #38            // java/io/PrintStream
  #33 = NameAndType        #39:#40        // println:(Ljava/lang/String;)V
  #34 = Utf8               java/lang/Object
  #35 = Utf8               java/lang/System
  #36 = Utf8               out
  #37 = Utf8               Ljava/io/PrintStream;
  #38 = Utf8               java/io/PrintStream
  #39 = Utf8               println
  #40 = Utf8               (Ljava/lang/String;)V
{
  public com.learning.stack.local_variables.LocalVariableTest();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 7: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/learning/stack/local_variables/LocalVariableTest;

  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           #2                  // class com/learning/stack/local_variables/LocalVariableTest
         3: dup
         4: invokespecial #3                  // Method "<init>":()V
         7: astore_1
         8: bipush        10
        10: istore_2
        11: aload_1
        12: invokespecial #4                  // Method print:()V
        15: return
      LineNumberTable:
        line 9: 0
        line 10: 8
        line 11: 11
        line 12: 15
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      16     0  args   [Ljava/lang/String;
            8       8     1 localVariableTest   Lcom/learning/stack/local_variables/LocalVariableTest;
           11       5     2   num   I
}
SourceFile: "LocalVariableTest.java"
  • 2.图示说明
    在这里插入图片描述
2.3 jclasslib插件查看
  • 1.字节码
    在这里插入图片描述

  • 2.异常表
    在这里插入图片描述

  • 3.杂项
    在这里插入图片描述

  • 4.slot槽位
    在这里插入图片描述

三、对slot的理解
3.1 说明
  • 1. 参数值的存放总是在局部变量数组的index0开始,到数组长度-1的索引结束
  • 2. 局部变量表,最基本的存储单元是slot(变量槽)
  • 3. 局部变量表中存放编译器可知的各种基本数据类型(8种),引用类型(reference),returnAddress类型的变量
  • 4.在局部变量表里,32位以内的类型只占用一个slot(包括returnAddress类型),64位的类型(long和double)占用两个slot
  • 5.byte、short、char在存储前被转换为int,boolean也被转为int,0表示false,非0表示true
  • 6. long和double则占据两个slot
  • 7. float占1个slot
  • 8. 引用类型也是32位,占1个slot
  • 9. jvm会为局部变量表中的每一个slot都分配一个访问索引,通过这个索引即可成功访问到局部变量表中指定的局部变量值
  • 10. 当一个实例方法被调用的时候,它的方法参数和方法体内部定义的局部变量将会按照顺序被复制到局部变量表中的每一个slot上
  • 11. 如果需要访问局部变量表中一个64bit的局部变量值时,只需要使用前一个索引即可。比如访问long或double类型变量
  • 12. 如果当前帧是由构造方法或者实例方法创建的,该对象引用this将会存放在index为0的slot处,其余的参数按照参数表顺序继续排列
  • 13. 静态方法中不能用this,是因为静态方法的局部变量表中没有this变量。构造方法和类实例方法的本地变量表index为0的slot处会存放this变量
3.2 slot索引图

在这里插入图片描述

3.3 实例方法的局部变量表

在这里插入图片描述

3.4 long和double类型变量占2个slot

在这里插入图片描述

四、slot的重复利用
4.1 说明
  • 1.栈帧中的局部变量表中的槽位是可以重复利用的
  • 2.如果一个局部变量过了其作用域,在其作用域之后申明的新的局部变量有可能会复用过期的局部变量的槽位,达到节省资源空间的目的
4.2 变量c复用变量b的槽位

在这里插入图片描述

五、静态变量与局部变量对比
  • 1. 参数表分配完毕之后,再根据方法体内定义的变量的顺序和作用域分配
  • 2. 类变量表有两次初始化的机会,第一次是在准备阶段,执行系统初始化,对类变量设置零值,第二次是在初始化阶段,赋予程序员在代码中定义的初始值
  • 3. 局部变量表不存在系统初始化的过程,一旦定义了局部变量则必须程序员来初始化,否则无法使用
  • 4.下面代码是错误的,没有赋值不能使用
    在这里插入图片描述
  • 5. 成员变量在使用前,都经历过默认初始化赋值
  • 6. 成员变量中的类变量在linking的prepare阶段给类变量默认赋值,initial阶段给类变量显示赋值即静态代码块赋值
  • 7. 成员变量中的实例变量随着对象
  • 8. 局部变量在使用前必须要进行显示赋值,否则编译不通过

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1107561.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NEFU计算机网络实验一常见网络命令的使用

一、实验目的 1、理解、验证常用网络命令的原理和功能。 2、掌握常用的网络命令使用方法&#xff0c;合理使用相关命令对网络进行管理与维护。 二、实验内容 网络参数查询命令&#xff1a;IPCONFIG 网络测试命令&#xff1a;ping 路由表命令ROUTE 网络端口查询命令&…

chatglm配置

推荐看这个链接&#xff0c;有些问题解决出处https://zhuanlan.zhihu.com/p/643824521 以及这个https://blog.csdn.net/weixin_40547993/article/details/131775275 1.需要pytorch2.0&#xff0c;所以CUDA推荐11.8 ChatGLM2-6B版本要装PYTORCH2.0&#xff0c;而且要2.0.1 &a…

resultMap 和 resultType的用法和区别详解

resultMap 和 resultType的用法和区别详解 《resultMap 和 resultType的用法和区别详解》摘要引言resultType - 用法和映射示例了解resultType示例演示 resultMap - 区别、高级用法和自定义映射规则详解resultType vs. resultMap高级用法示例演示 Mybatis的CRUD操作总结参考资料…

信息保卫战:揭秘迅软DSE护航企业免受泄密之害

随着网络技术的发展&#xff0c;通过网络应用如网盘、网页、邮件、即时通讯工具传输分享文件变得越来越多&#xff0c;这些工具传输速度快&#xff0c;能够将大容量的文档快速传送给他人&#xff0c;在工作中受到许多人的青睐。 然而由这些传输工具引发的泄密事件也不断增多&am…

进程概念[下]

一、 进程优先级 0x01 什么叫进程优先级 CPU资源分配的先后顺序 0x02 为什么要有进程优先级 因为资源不足,是分配资源的一种方式,优先权高的进程有优先执行权利 0x03 查看更加详细的进程信息 ①运行代码 #include<iostream> #include<unistd.h> using na…

Cesium 空间量算——方位角量测

文章目录 需求分析需求 实现对方位角的量测功能 分析 可以通过Cesium API提供的方法手动实现方位角测量。下面是一个可以帮助你开始实现方位角测量的代码示例: // 初始化Cesium Viewer var viewer = new Cesium.Viewer(cesiumContainer);// 创建材质

第六章redux的使用(餐饮版)

文章目录 一、redux的使用1、redux原理图解析 二、同步计算器案例2、创建src/redux/constant.js&#xff08;食材库&#xff09;3、创建src/redux/store.js&#xff08;厨房&#xff09;3-1、安装redux3-2、store.js 4、count_reducer.js&#xff08;厨师&#xff09;5、count_…

如何从SEO角度写好原创文章并吸引人

不会写原创文章的站长&#xff0c;不能算是好的站长哦。SEO原创文章对于网站优化来说&#xff0c;就像吃饭对于人的生存一样重要。如果一个SEO博客全是复制粘贴别人的文章&#xff0c;那这个博客还有多少意义呢&#xff1f;这就好比别人辛苦种田&#xff0c;你却轻易地把人家的…

Profinet转Modbus RTU网关连接PLC与多功能电表modbus通讯配置案例

Profinet是一种工业以太网通讯协议&#xff0c;广泛用于工业自动化系统中。而Modbus RTU是一种串行通信协议&#xff0c;常用于PLC和仪表之间的通讯。Profinet转Modbus RTU网关(XD-MDPN100)的作用就是将Profinet协议转换为Modbus RTU协议&#xff0c;从而实现PLC和多功能电表之…

zabbix-agnet连接zabbix-proxy

先配置好zabbix-proxy zabbix-proxy配置http://t.csdnimg.cn/RpaCI 在zabbix-proxy服务器上 [rootcloudserver ~]# grep ^[a-Z] /etc/zabbix/zabbix_agentd.conf PidFile/var/run/zabbix/zabbix_agentd.pid LogFile/var/log/zabbix/zabbix_agentd.log LogFileSize0 Server19…

Java 常用类(包装类)

目录 八大Wrapper类包装类的分类 装箱和拆箱包装类和基本数据类型之间的转换常见面试题 包装类方法包装类型和String类型的相互转换包装类常用方法&#xff08;以Integer类和Character类为例&#xff09;Integer类和Character类的常用方法 Integer创建机制&#xff08;面试题&a…

ims-ui项目搭建

node版本&#xff1a; npm版本&#xff1a; 创建vite项目&#xff1a; npm create vitelatest 使用的vite版本为&#xff1a; 安装router4,安装命令如下&#xff1a; npm install vue-router4 安装pinia&#xff0c;安装命令如下&#xff1a; npm install pinia 安装Pinia持…

SLAM从入门到精通(利用数据集来离线制图)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们的测试大部分都是基于仿真来实现的。但是很多时候&#xff0c;我们其实希还是望自己的算法能够跑在真实场景的数据上。可问题来了&#xf…

MinIO (二) .net core中实现上传下载

这篇文章里&#xff0c;我们介绍在.net core webapi项目中操作MinIO。 首先要创建一个桶&#xff0c;命名为demo 英文文档看不太顺畅&#xff0c;在网上找了一个api中文文档&#xff0c;可供参考 .NET Client API参考文档 - MinIO 帮助文档 - 开发文档 - 文江博客 创建桶 点…

偏偏不信文心大模型4.0比肩GPT-4!我为它们安排了一场龙虎斗!

作者 | 卖萌酱 大家好&#xff0c;我是卖萌酱。盲猜点进本文的不少小伙伴也看了昨天的百度世界大会&#xff0c;百度创始人、董事长兼CEO李彦宏官宣文心大模型4.0发布&#xff0c;其中一句话让卖萌酱印象深刻&#xff1a;文心大模型4.0综合水平与GPT-4相比已经毫不逊色&#xf…

python二次开发Solidworks:画砂轮

先根据输入参数计算出绘制砂轮需要的数据&#xff0c;然后绘制草图&#xff0c;完全标注后生成旋转体&#xff0c;具体代码如下&#xff1a; import sympy as sy import numpy as np import matplotlib.pyplot as pltx1,y1为第一条直线端点坐标(-10,0),theta_l1为角度,取5*np.…

C语言实现用弦截法求 f(x)=x^3-5*x^2+16*x-80=0 的根

完整代码: //用弦截法求 func(x)x^3-5*x^216*x-800 的根 //弦截法就是用函数上两点&#xff0c;连线的斜率近似代替f(x) //公式为Xn1Xn−(Xn−Xn−1)*func(Xn)/(func(Xn)−f(Xn−1))#include<stdio.h> #include<math.h>//求f(x)的值 double func(double x){return…

博客后台模块

一、后台模块-准备工作 1. 前端工程启动 前端工程下载链接 https://pan.baidu.com/s/1TdFs4TqxlHh4DXyLwYuejQ 提取码&#xff1a;mfkw 项目sql文件下载链接 链接&#xff1a;https://pan.baidu.com/s/1DQCGN4wISSDlOkqnVWYwxA 提取码&#xff1a;mfkw 命令行进入keke-vu…

工业4.0时代数字化工厂的几个特点

随着工业4.0时代的到来&#xff0c;数字化工厂成为了制造业的重要组成部分。数字化工厂管理系统是一种应用数字化、自动化和物联网等技术与产业融合的全新生产方式&#xff0c;旨在提高生产效率、降低成本、提升产品质量&#xff0c;并增强企业的核心竞争力。 数字化工厂的核心…

用友GRP-U8 SQL注入漏洞复现

0x01 产品简介 用友GRP-U8R10行政事业财务管理软件是用友公司专注于国家电子政务事业&#xff0c;基于云计算技术所推出的新一代产品&#xff0c;是我国行政事业财务领域最专业的政府财务管理软件。 0x02 漏洞概述 用友GRP-U8的bx_historyDataCheck jsp、slbmbygr.jsp等接口存…