【JVM】JVM内存结构之——栈帧内部结构原理分析

本文详细解析了Java虚拟机(JVM)中的局部变量表,包括变量槽(Slot)的概念,以及如何通过jclasslib分析字节码。局部变量表仅在方法调用期间有效,存储参数和局部变量,其变量槽根据数据类型分配,复用机制节省空间。此外,还探讨了`this`关键字的底层原理,`++i`与`i++`的区别,以及栈溢出和动态链接的现象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


在这里插入图片描述

1. 局部变量表

public static void main(String[] args) {
    String str = "demo01";
    int j = 20;
    double d = 66.66;
    boolean b = true;
}

局部变量表中的变量只在当前方法调用中有效。在方法执行时,虚拟机通过使用局部变量表完成参数值到参数变量列表的传递过程。当方法调用结束后,随着方法栈帧的销毁,局部变量表也会随之销毁。

2. Slot(变量槽–index)

局部变量表最基本的存储单元就是变量槽。
在局部变量表里,32位以内的类型只占用一个slot (包括returnAddress类型),64位的类型(long和double)占用两个slot。
注意:short,byte,boolean等数据也占用一个变量槽,因为jvm会在存储时将上述变量转为int类型(变量槽是最基本存储单元,无法分割,只能整个使用)。

在这里插入图片描述
JVM会为局部变量表中每一个变量分配变量槽,并记录其的存储位置,比如main函数方法传递了String [] args 数组 变量args就存储在index为0的变量槽中,变量d因为为64位,需要占用两个变量槽(3和4),变量b因为D占用了两个变量槽,所以直接从index5处开始存储。
在这里插入图片描述

3. jclasslib分析字节码

  1. idea 安装使用
    打开idea 中的settings > plugins 搜索 jclasslib 插件 进行安装 重启生效
    重启后点击view > 选择show bytecode with jclasslib
  2. jclasslib git地址:https://github.com/ingokegel/jclasslib
    在这里插入图片描述
    在这里插入图片描述

4. 变量槽的复用

public static void demo002() {
    int a = 0;
    {
        int b=30;
        System.out.println("demo01");
    }
    int c = 0;
}

在这里插入图片描述
此处原因就是JVM对变量槽有一个复用性为,当变量b超出其作用域后不再生效,所以变量c直接占据了b的位置,所以局部变量表中会少一个位置。

5. This底层原理

如果当前的方法是实例方法或者是构造方法,则jvm默认会在局部变量表中创建 一个
当前对象 变量名称为 this, 存入在我们当前方法对应的局部表 第0个位置 这样我们就可以在实例方法中 使用 this,静态方法不会。
代码演示:

public void demo() {
    int j = 20;
}

在这里插入图片描述

6. 局部变量表总结

局部变量表只对已确定一定有值的变量和方法参数进行记录,在程序执行中得以直接使用,存储在量变槽中,如果是long和double,则需要占用两个变量槽,实例方法和构造方法会自动创建this变量,并且如果代码块结束(作用域结束),jvm会对变量槽有一个复用的行为,以便于节省空间。

7. 操作数栈分析

相关代码:

public int compute() {
    int a = 10;
    int b = 20;
    int c = (a + b) * 10;
    return c;
}

iconst_0:将int类型的0值压入操作数栈
istore_1: 弹出操作数栈顶的值赋给局部变量表下标为1的变量
iload_1: 将局部变量表下标为1的位置存储的值压入操作数栈
iinc 1 by 1:取局部变量表下标为1的位置存储的值加上1
istore_1:弹出操作数栈顶的值赋给局部变量表下标为1的变量

底层汇编代码:
0: bipush 10 ## 将一个8位带符号整数压入栈
2: istore_1 局部变量表中槽1的位置存入10;
3: bipush 20 ## 将一个8位带符号整数压入栈 20
5: istore_2 局部变量表中槽2的位置存入20;
6: iload_1 从局部变量表中槽1的位置 获取 变量a=10;
7: iload_2 从局部变量表中槽2的位置 获取 变量b=20;
8: iadd iadd 执行int类型的加法 10+20
9: bipush 将一个8位带符号整数压入栈 10
11: imul imul 执行int类型的乘法30*10
12: istore_3 局部变量表中槽3的位置存入300 c=300;
13: iload_3 最后返回局部变量表中槽3的位置
14: ireturn

8. ++i与i++的底层原理

i++是先赋值,然后再自增;++i是先自增,后赋值。

i++是直接在局部变量表加的,没有在操作数栈里运算
I++ 与++i底层区别

I++ 先将局部变量表中的值 压入放入到操作数栈中
,在直接对局部变量中做+1操作。
++i 先将局部变量表中的 值 做1+的操作,在将局部变量表中 加1
之后的结果 压入到操作数栈中。

动态连接–常量池
方法出口 定义异常

9. 栈溢出

StackOverflowError(栈溢出)
StackOverflowError代表的是,当栈深度超过虚拟机分配给线程的栈大小时就会出现此error。

public class StackOverFlow {
    private int i;

    public void plus() {
        i++;
        plus();
    }

    public static void main(String[] args) {
        StackOverFlow stackOverFlow = new StackOverFlow();
        try {
            stackOverFlow.plus();
        } catch (Error e) {
            System.out.println("Error:stack length:" + stackOverFlow.i);
            e.printStackTrace();
        }
    }
}


10. 动态链接

动态链接: 每个栈帧都保存了 一个可以指向当前方法所在类的 运行时常量池, 目的是: 当前方法中如果需要调用其他方法的时候, 能够从运行时常量池中找到对应的符号引用, 然后将符号引用转换为直接引用,然后就能直接调用对应方法, 这就是动态链接

11. 方法出口

方法返回地址

### 关于 UniApp 框架推荐资源与教程 #### 1. **Uniapp 官方文档** 官方文档是最权威的学习资料之一,涵盖了从基础概念到高级特性的全方位讲解。对于初学者来说,这是了解 UniApp 架构技术细节的最佳起点[^3]。 #### 2. **《Uniapp 从入门到精通:案例分析与最佳实践》** 该文章提供了系统的知识体系,帮助开发者掌握 Uniapp 的基础知识、实际应用以及开发过程中的最佳实践方法。它不仅适合新手快速上手,也能够为有经验的开发者提供深入的技术指导[^1]。 #### 3. **ThorUI-uniapp 开源项目教程** 这是一个专注于 UI 组件库设计实现的教学材料,基于 ThorUI 提供了一系列实用的功能模块。通过学习此开源项目的具体实现方式,可以更好地理解如何高效构建美观且一致的应用界面[^2]。 #### 4. **跨平台开发利器:UniApp 全面解析与实践指南** 这篇文章按照章节形式详细阐述了 UniApp 的各个方面,包括但不限于其工作原理、技术栈介绍、开发环境配置等内容,并附带丰富的实例演示来辅助说明理论知识点。 以下是几个重要的主题摘选: - **核心特性解析**:解释了跨端运行机制、底层架构组成及其主要功能特点。 - **开发实践指南**:给出了具体的页面编写样例代码,展示了不同设备间 API 调用的方法论。 - **性能优化建议**:针对启动时间缩短、图形绘制效率提升等方面提出了可行策略。 ```javascript // 示例代码片段展示条件编译语法 export default { methods: { showPlatform() { console.log(process.env.UNI_PLATFORM); // 输出当前平台名称 #ifdef APP-PLUS console.log('Running on App'); #endif #ifdef H5 console.log('Running on Web'); #endif } } } ``` #### 5. **其他补充资源** 除了上述提到的内容外,还有许多在线课程视频可供选择,比如 Bilibili 上的一些免费系列讲座;另外 GitHub GitCode 平台上也有不少优质的社区贡献作品值得借鉴研究。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超级码里喵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值