【jvm】虚拟机栈之操作数栈

news2024/10/5 17:18:49

目录

        • 一、说明
        • 二、图解
          • 2.1 代码示例
          • 2.2 javap操作
        • 三、图示
          • 3.1 bipush 15
          • 3.2 istore_1
          • 3.3 bipush 8
          • 3.4 istore_2
          • 3.5 iload_1
          • 3.6 iload_2
          • 3.7 iadd
          • 3.8 istore_3
          • 3.9 return结束
        • 四、附加

一、说明
  • 1.Operand Stack
  • 2.栈可以使用数组或链表来实现
  • 3.每一个独立的栈帧包含一个后进先出(Last-In-First-Out)的操作数栈
  • 4.也可称为表达式栈(expression stack)
  • 5.操作数栈在方法执行过程中,根据字节码指令,往栈中写入数据或提取数据,即入栈(push)/出栈(pop)
  • 6.某些字节码指令将值压入操作数栈,其余的字节码指令将操作数取出栈,使用它们后再把结果压入栈
  • 7.可以用来执行复制、交换、求和等操作
  • 8.操作数栈主要用于保存计算过程的中间结果,同时作为计算过程中变量临时的存储空间
  • 9.操作数栈是jvm执行引擎的一个工作区,当一个方法刚开始执行的时候,一个新的栈帧也会被创建出来,这个方法的操作数栈是空的
  • 10.每一个操作数栈都拥有一个明确的栈深度用于存储数值,所需的最大深度在编译器定义好了,保存在方法的code属性,为max_stack的值
  • 11.栈中的任何一个元素都是可以任意的java数据类型,32bit的类型占用一个栈单位深度,64bit的类型占用两个栈单位深度
  • 12.操作数栈并非采用访问索引的方式来进行数据访问,只能通过标准的入栈(push)和出栈(pop)操作来完成一次数据访问
  • 13.被调用的方法带有返回值,其返回值将会被压入当前栈帧的操作数栈中,并更新pc寄存器中下一条需要执行的字节码指令
  • 14.操作数栈中元素的数据类型必须与字节码指令的序列严格匹配,这由编译器在编译器期间进行验证,同时在类加载过程中的类检验阶段的数据流分析阶段要再次验证
  • 15.java虚拟机的解释引擎是基于栈的执行引擎,该栈指的就是操作数栈
二、图解
2.1 代码示例
package com.learning.stack.operand_stack;

/**
 * @Author wangyouhui
 * @Description 操作数栈
 **/
public class OperandStackTest {
    public static void main(String[] args) {
        byte i = 15;
        int j = 8;
        int k = i + j;
    }
}
2.2 javap操作
javap -v OperandStackTest.class
Classfile /F:/jdk-learning/jvm/target/classes/com/learning/stack/operand_stack/OperandStackTest.class
  Last modified 2023-10-22; size 529 bytes
  MD5 checksum 82f8abcaba4fd78948113a564c4f83a1
  Compiled from "OperandStackTest.java"
public class com.learning.stack.operand_stack.OperandStackTest
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #3.#22         // java/lang/Object."<init>":()V
   #2 = Class              #23            // com/learning/stack/operand_stack/OperandStackTest
   #3 = Class              #24            // java/lang/Object
   #4 = Utf8               <init>
   #5 = Utf8               ()V
   #6 = Utf8               Code
   #7 = Utf8               LineNumberTable
   #8 = Utf8               LocalVariableTable
   #9 = Utf8               this
  #10 = Utf8               Lcom/learning/stack/operand_stack/OperandStackTest;
  #11 = Utf8               main
  #12 = Utf8               ([Ljava/lang/String;)V
  #13 = Utf8               args
  #14 = Utf8               [Ljava/lang/String;
  #15 = Utf8               i
  #16 = Utf8               B
  #17 = Utf8               j
  #18 = Utf8               I
  #19 = Utf8               k
  #20 = Utf8               SourceFile
  #21 = Utf8               OperandStackTest.java
  #22 = NameAndType        #4:#5          // "<init>":()V
  #23 = Utf8               com/learning/stack/operand_stack/OperandStackTest
  #24 = Utf8               java/lang/Object
{
  public com.learning.stack.operand_stack.OperandStackTest();
    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/operand_stack/OperandStackTest;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=4, args_size=1
         0: bipush        15
         2: istore_1
         3: bipush        8
         5: istore_2
         6: iload_1
         7: iload_2
         8: iadd
         9: istore_3
        10: return
      LineNumberTable:
        line 9: 0
        line 10: 3
        line 11: 6
        line 12: 10
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      11     0  args   [Ljava/lang/String;
            3       8     1     i   B
            6       5     2     j   I
           10       1     3     k   I
}
SourceFile: "OperandStackTest.java"

三、图示
3.1 bipush 15
  • 1.操作数栈和局部变量表一开始是空的
  • 2.pc寄存器记录要操作的指令地址是0
  • 3.byte i = 15;
  • 4.byte、short、char、boolean、int都以int型来保存,bipush中b表示byte,i表示int
  • 5.bipush 15是将15push到操作数栈当中
    在这里插入图片描述
3.2 istore_1
  • 1.pc寄存器记录要操作的指令地址2
  • 2.istore_1将栈顶的15存到局部变量表索引为1的位置
  • 3.已经转化为int类型了,所以用istore
  • 4.非静态方法,局部变量表索引为0的位置是this变量,因此istore存的是索引为1的位置
  • 5.操作数栈的栈顶出栈后变为空的
    在这里插入图片描述
3.3 bipush 8
  • 1.pc寄存器记录要操作的指令地址3
  • 2.把8压入操作数栈的栈顶
    在这里插入图片描述
3.4 istore_2
  • 1.pc寄存器记录要操作的指令地址5
  • 2.将操作数栈的栈顶数据出栈,保存到局部变量表索引为2的位置
  • 3.操作数栈的栈顶数据出栈后,变为空
    在这里插入图片描述
3.5 iload_1
  • 1.pc寄存器记录要操作的指令地址6
  • 2.iload_1将局部变量表中索引为1位置的数据取出压入操作数栈的栈顶
    在这里插入图片描述
3.6 iload_2
  • 1.pc寄存器记录要操作的指令地址7
  • 2.iload_2将局部变量表中索引为2位置的数据取出压入操作数栈的栈顶
    在这里插入图片描述
3.7 iadd
  • 1.pc寄存器记录要操作的指令地址8
  • 2.iadd会弹出操作数栈栈顶的数据,执行引擎将字节码指令翻译为机器指令,从而让cpu计算俩数据的和23
    在这里插入图片描述
  • 3.iadd将cpu计算的结果23压入操作数栈的栈顶
    在这里插入图片描述
3.8 istore_3
  • 1.pc寄存器记录要操作的指令地址9
  • 2.istore_3将操作数栈的栈顶数据出栈,保存到局部变量表索引为3的位置
  • 3.操作数栈的栈顶数据出栈后,变为空
    在这里插入图片描述
3.9 return结束
四、附加
  • 1.操作数栈从一开始到结束,只用到2个空间,即最大深度为2,即stack=2
  • 2.局部变量表最大索引位置为3,局部变量表最大长度为4,索引为0的位置是this变量,即locals=4
    在这里插入图片描述
  • 3.尽量会以最小的范围来匹配push,例如byte范围为-128到127,在这个范围内的数会用bipush压入操作数栈,short范围为-32768到32727,当一个整数超过了byte范围,但还在short范围内,会用sipush压入操作数栈,以此类推

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

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

相关文章

Mac 开机提示Google LLC 注册 无法登录进入系统

Google LLC 会在电脑启动时提示如下弹窗&#xff0c;并要求登录谷歌账户进行验证 此时很明显没有用来进行验证的账号&#xff0c;所以需要关掉这个验证程序 从日志里面可以看到LLC启动了一个Tiny.app的程序 只需要想办法把这个程序删掉即可 关机 按住 Command R 开机 进入R…

【MySQL架构篇】MySQL字符集、大小写规范及默认数据库

文章目录 1. 字符集与字符集比较规则2. 大小写规范3. 默认数据库4. 与文件系统相关 1. 字符集与字符集比较规则 MySQL有4个级别的字符集和比较规则&#xff0c;分别是 服务器级别数据库级别表级别列级别 当创建对应表或列未指定字符集时&#xff0c;默认会取其上一级别的字符…

JavaScript-1-菜鸟教程

将内容写到 HTML 文档中 - - - document.write() <script>// 括号里的内容要有引号document.write("<h1>这是一个标题</h1>");document.write(<div class"box">hello world</div>);</script><style>.box{width…

如何部署lvs负载均衡集群 DR模式

Lvs _DR 模式 也是最常见的lv负载方式 DR DIRECT ROUTING 直接路由模式 DR模式工作过程 1 .客户端请求vip 2、LVS的调度器接受请求之后&#xff0c;根据算法选择一台后端的真实服务器&#xff0c; 请求转发到后端RS,请求的报 文的目的MAC地址&#xff0c;修改成后端真实服务器的…

同为科技(TOWE)大功率带机械联锁工业插头插座箱

所谓工业机械联锁开关插座&#xff0c;是一种工业用途插座&#xff0c;带有一个旋钮开关&#xff0c;通过旋钮开关可以控制电源的通断。其特点是具有联动锁定机构&#xff0c;当旋钮开关断开操作后&#xff0c;联动锁定机构会自动撤销限位&#xff0c;使插头能够插入或拔出。当…

RabbitMQ基础篇 笔记

RabbitMQ 余额支付 同步调用 一步一步的来&#xff0c;支付业务写完后&#xff0c;如果之后加需求&#xff0c;还需要增加代码&#xff0c;不符合开闭原则。 性能上也有问题&#xff0c;openfeign是同步调用&#xff0c;性能太差。 同步调用耦合太多。 同步的优势是可以立…

Node编写用户登录接口

目录 前言 服务器 编写登录接口API 使用sql语句查询数据库中是否有该用户 判断密码是否正确 生成JWT的Token字符串 配置解析token的中间件 配置捕获错误中间件 完整的登录接口代码 前言 本文介绍如何使用node编写登录接口以及解密生成token&#xff0c;如何编写注册接…

侯捷C++面向对象程序设计笔记(上)-Object Based(基于对象)部分

基于对象就是对于单一class的设计。 对于有指针的&#xff1a;complex.h complex-test.cpp 对于没有指针的&#xff1a; string.h string-test.cpp https://blog.csdn.net/ncepu_Chen/article/details/113843775?spm1001.2014.3001.5501#commentBox 没有指针成员——以复数co…

【单片机学习笔记】Windows+Vscode+STM32F4+freeRTOS+FatFs gcc环境搭建

为摒弃在接受keil邮件&#xff0c;研究了下gun编译&#xff0c;以STM32F407为例&#xff0c;简单记录 1. 软件包准备 Git 选择对应版本直接安装即可https://git-scm.com/download/winmakegcc ​ 1&#xff09;将上述软件包放置于C盘根目录 2&#xff09;添加环境变量 3&am…

分类预测 | MATLAB实现SSA-CNN-BiLSTM-Attention数据分类预测(SE注意力机制)

分类预测 | MATLAB实现SSA-CNN-BiLSTM-Attention数据分类预测&#xff08;SE注意力机制&#xff09; 目录 分类预测 | MATLAB实现SSA-CNN-BiLSTM-Attention数据分类预测&#xff08;SE注意力机制&#xff09;分类效果基本描述模型描述程序设计参考资料 分类效果 基本描述 1.MAT…

Android View拖拽startDragAndDrop,Kotlin

Android View拖拽startDragAndDrop&#xff0c;Kotlin import android.os.Bundle import android.util.Log import android.view.DragEvent import android.view.View import android.view.View.OnDragListener import android.view.View.OnLongClickListener import android.w…

Spring中方法拦截器

一、MethodInterceptor 在动态代理中要想添加一个额外功能&#xff0c;只要去实现MethodBeforeAdvice这个接口就行了&#xff0c;但是实现了这个接口的额外功能只能运行在目标类执行之前&#xff0c;如果是想在目标类执行之后呢&#xff1f;那这个需求就完成不了&#xff0c;所…

SpringBoot Lombok的使用

目录 下载Lombok插件 Lombok的用法 获取日志对象 生成get,set方法 Lombok框架的实现原理 Lombok的常用注解 下载Lombok插件 要使用Lombok首先要确保idea安装了lombok插件 在项目中添加 lombok依赖 在<dependency>里右键生成点击edit starters 插件(没有就下载,可…

行业模型应该如何去拆解?

行业模型应该如何去拆解&#xff1f; 拆解行业模型是一个复杂的过程&#xff0c;涉及对整个行业的深入分析和理解。下面是一些步骤和方法&#xff0c;可以帮助你系统地拆解行业模型&#xff1a; 1. 确定行业范围 定义行业&#xff1a;明确你要分析的行业是什么&#xff0c;包括…

寻找二叉树一个节点的后继节点

后继节点&#xff1a;中序遍历的后一个节点 普通二叉树&#xff1a;中序遍历得到一个list&#xff0c;时间复杂度O(n) 本题的二叉树&#xff1a;有父节点的指针&#xff0c;后继节点与原节点的距离为1&#xff0c;因此可以直接通过父节点找到下一个节点 优化&#xff1a;节点…

出差学小白知识No6:LD_PRELOAD变量路径不对找不到库文件

交叉编译的时候出现以下问题&#xff0c;显示LD_PRELOAD变量找不到路劲 首先先查看一下LD_PRELOAD的路径&#xff1a;echo $LD_PRELOAD 如果输出一大串&#xff0c;那么先进行清空&#xff1a;unset LD_PRELOAD 重新给LD_PRELOAD进行赋值他的路径和库文件&#xff1a; expor…

亚马逊、eBay、wish、Lazada、shoppe和mercari如何降低测评成本提高测评效率?

测评&#xff08;补单&#xff09;是跨境卖家在如亚马逊、Lazada、Shopee、wish、eBay、速卖通、阿里国际、沃尔玛、newegg、mercari等平台运营中不可或缺的需求。近年来&#xff0c;测评技巧在跨境卖家圈中越来越活跃。那么为什么跨境测评对于亚马逊卖家来说如此重要呢&#x…

【Leetcode】 213. 打家劫舍 II ?

你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋&#xff0c;每间房内都藏有一定的现金。这个地方所有的房屋都围成一圈&#xff0c;这意味着第一个房屋和最后一个房屋是紧挨着的。同时&#xff0c;相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚…

Java反射实体组装SQL

之前在LIS.Core定义了实体特性&#xff0c;在LIS.Model给实体类加了表特性&#xff0c;属性特性&#xff0c;外键特性等。ORM要实现增删改查和查带外键的父表信息就需要解析Model的特性和实体信息组装SQL来供数据库驱动实现增删改查功能。 实现实体得到SQL的工具类&#xff0c…

视觉SLAM十四讲-第三讲三维刚体运动

什么是刚体运动以及三维空间中刚体运动描述方式有哪些&#xff1f; 两个坐标系之间的运动由一个旋转加上一个平移组成&#xff0c;这种运动称为刚体运动。描述三维空间中刚体运动的方式有旋转矩阵、旋转向量、欧拉角、四元数。 请描述左手坐标系和右手坐标系。 大拇指——y …