深入理解java虚拟机--虚拟机栈之局部变量表和操作数栈 剖析

一、概念

Java虚拟机栈(Java Virtual Machine Stack)

虚拟机栈描述的是Java方法执行的线程内存模型:每个方法被执行的时候,Java虚拟机都会同步创建一个栈帧(Stack Frame)用于存储局部变量表、操作数栈、动态连接、方法出口等信息。每一个方法被调用直至执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。它是线程私有的,它的生命周期与线程相同。(摘自深入理解Java虚拟机-第三版

  • 栈帧:虚拟机栈中的最小执行单元(每一个栈帧对应一个java方法)
  • 局部变量表:一组变量值的存储空间,用于存放方法参数及内部定义的局部变量。
    • 变量槽:局部变量表以最小单位-变量槽来表示
  • 操作数栈:也常被称为操作栈,它是一个后入先出(Last InFirst Out,LIFO)栈

                                           Java虚拟机栈执行示意图

二、概念剖析

变量槽

1》 一个变量槽可以存放一个32位以内的数据类型,Java中占用不超过32位存储空间的数据类型有boolean、byte、char、short、int、float、reference和returnAddress这8种类型。

注:reference类型表示对一个对象实例的引用---简单理解为:通过引用可找到真实对象地址或类型信息等(本章不扩展

2》对于64位的数据类型,Java虚拟机会以高位对齐的方式为其分配两个连续的变量槽空间。Java语言中明确的64位的数据类型只有long和double两种

访问:Java虚拟机通过索引定位的方式使用局部变量表,索引值的范围是从0开始至局部变量表最大的变量槽数量。如果访问的是32位数据类型的变量,索引N就代表了使用第N个变量槽,如果访问的是64位数据类型的变量,则说明会同时使用第N和N+1两个变量槽。

【简汇: 索引值从0开始,32位数--->第N个变量槽  64位数--->第(N 和N+1)变量槽】

三、操作数栈 + 局部变量表执行示意图分析

目的:计算c = a + b的值

一、代码示例:

    public int add() {
        int a = 100;
        int b = 200;
        int c = a + b;
        return c;
    }

 

二、字节码示例及含义

字节码指令
字节码含义示例释义
bipush Push bytebipush 100字节立即被符号扩展为int值,该值被压入操作数栈中
istore_n

Store int into local variable

istore_1

索引1是一个无符号字节,必须是当前栈帧的局部变量数组的索引,操作数栈顶值必须是int类型。

它从操作数栈中弹出,并且索引值1的局部变量表的值设置为对应value 

sipush

Push short

sipush 200无符号立即数byte1和byte2的值组合成一个中间short,其中short的值为(byte1 << 8)| 字节2。 然后将中间值符号扩展为int值。 该值被压入操作数堆栈。
iload_n

Load int from local variable

iload_1或iload_2索引处(1|2)的局部变量必须包含一个int。 索引处的局部变量的值被压入操作数堆栈。
iadd

Add int

 

(栈中取2数值相加的结果:

..., value1value2 →

..., result

iadd

value1和value2都必须为int类型。 从操作数堆栈中弹出值。 int结果为value1 + value2。 结果被压入操作数堆栈。

(结果是具有足够宽的二进制补码格式的真实数学结果的32个低位,表示为int类型的值。 如果发生溢出,则结果的符号可能与两个值的数学和的符号不同。

尽管可能会发生溢出,但是执行iadd指令绝不会引发运行时异常)

ireturn

Return int from method

ireturn从当前帧的操作数堆栈中弹出值,并将其压入调用者的帧的操作数堆栈。 当前方法的操作数堆栈上的任何其他值都将被丢弃

 

 

 

 

 

更多参考【字节码指令官方地址


三、代码指令执行示意图

注:以下按照字节码执行指令顺序分析,请参考下图即可


 





以上则是java虚拟机栈之操作数栈+局部变量表执行示意图,作为个人学习及分享记录,如有误请指正,谢谢。

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
### 回答1: 非常感谢您使用 CSDN 提供的 C 语言知识来和我进行交流。我是一个 AI 语言模型,虽然我和 ChatGPT 和 OpenAI 没有任何直接关系,但我会尽力回答您的问题。 关于您的问题,我理解您想了解 Java 虚拟机内存分哪几个区域,每个区域的作用是什么。这是一个比较具体的技术问题,需要有相关的 Java 知识才能够回答,我会尽力给您提供一些帮助。 Java 虚拟机内存主要分为以下几个区域: 1. 程序计数器区域:这是一块较小的内存区域,主要用于记录线程执行的字节码指令地址,为线程切换后能够恢复执行位置提供支持。 2. Java 虚拟机区域:这个区域也称为内存,主要用于存放线程私有的本地变量、操作数、方法出口等信息。 3. Java 堆区域:这个区域是 Java 内存管理中最大的一块区域,用于存放 Java 对象实例和数组对象。 4. 方法区域:这个区域也称为永久代(在 JDK 8 及之前版本)或元空间(在 JDK 8 及之后版本),主要用于存放类信息、常量、静态变量等数据。 5. 本地方法:这个区域与 Java 虚拟机类似,但是主要是为了支持 JNI(Java Native Interface)而设计的。 每个区域的作用和使用方法可以根据具体的应用场景和需求而不同,需要根据具体的问题来进行分析和解答。如果您有更具体的问题,可以在 CSDN 社区中提出,也可以向其他 Java 开发者寻求帮助。 最后提醒您注意使用中文进行提问和回答,这样可以保证更好的沟通和交流。 ### 回答2: Java虚拟机的内存分为以下几个区域: 1. 方法区(Method Area):用于存放类的结构信息,如类的代码、字段、方法、静态变量等。方法区在虚拟机启动时被创建,并在虚拟机退出时被销毁。 2. 堆(Heap):堆是用于存储对象实例的区域。所有的对象实例和数组都在堆中分配内存。堆是Java虚拟机管理的最大一块内存区域,也是垃圾收集器的主要工作区域。 3. 虚拟机(VM Stack):用于存储方法的局部变量操作数、动态链接和方法返回值等。每个线程在创建时都会在虚拟机中创建一个帧,用于存储方法的相关信息。帧随着方法的进入和退出而创建和销毁。 4. 本地方法(Native Method Stack):本地方法虚拟机类似,但用于执行本地方法(即使用其他编程语言编写的方法,如C语言)。本地方法也是帧的存储区域,但主要用于执行本地方法。 5. 程序计数器(Program Counter Register):程序计数器是一块较小的内存区域,用于存储当前线程所执行的字节码指令的地址。每个线程都有一个独立的程序计数器,用于线程切换后能恢复到正确的执行位置。 这些内存区域各自担负不同的任务:方法区存储类的结构信息,堆存储对象实例,虚拟机和本地方法存储方法相关信息,程序计数器用于指示线程当前执行的字节码指令地址。这些区域的合理使用和管理对于Java程序的性能和内存消耗具有重要意义。 ### 回答3: Java虚拟机内存分为以下几个区域: 1. 程序计数器:是一块较小的内存区域,用于记录当前线程所执行的字节码指令的地址。在线程切换时,程序计数器会被保存和恢复,确保线程能够正确执行。 2. Java虚拟机:每个线程在创建时都会同时创建一个,用于存储方法调用和局部变量中的每个帧对应一个方法调用,包括方法的参数、局部变量、返回值等。的大小是固定的,中的数据是线程私有的。 3. 本地方法:与Java虚拟机类似,但为本地方法服务。本地方法是使用其他语言编写的,通过JNI(Java Native Interface)方式调用。 4. 堆区:是Java虚拟机中最大的一块内存区域,用于存储创建的对象实例和数组。所有线程共享堆,但每个对象都拥有自己的内存空间。堆可以分为新生代和老年代,用于实现垃圾回收。 5. 方法区(元数据区):用于存储类的信息、常量池、静态变量、即时编译器编译后的代码等。方法区是所有线程共享的,存放加载的类信息,属于永久性区域。 6. 运行时常量池:是方法区的一部分,用于存放编译期生成的各种字面量和符号引用。 每个区域的作用如下: - 程序计数器:记录当前线程所执行的字节码指令的位置,确保线程切换后能继续执行。 - Java虚拟机:用于存储方法的局部变量和方法调用的信息,方法调用结束后会自动释放。 - 本地方法:与Java虚拟机类似,但专门用于本地方法的调用。 - 堆区:存储对象和数组,是垃圾回收的重点区域。堆分为新生代和老年代,以支持不同的对象分配和垃圾回收策略。 - 方法区(元数据区):存储类的相关信息,如类的字段、方法、常量池、即时编译器编译后的代码等。 - 运行时常量池:存放编译期生成的各种字面量和符号引用,通常会存储在方法区中。 这些内存区域共同构成了Java虚拟机的内存结构,保证了Java程序的正常执行。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值