深入理解JVM虚拟机第二十二篇:详解JVM当中与操作数栈相关的字节码指令

大神链接:作者有幸结识技术大神孙哥为好友,获益匪浅。现在把孙哥视频分享给大家。

孙哥链接:孙哥个人主页
作者简介:一个颜值99分,只比孙哥差一点的程序员
本专栏简介:话不多说,让我们一起干翻JVM

本文章简介:话不多说,让我们讲清楚JVM当中与操作数栈相关的字节码指令

文章目录

一: 操作数栈字节码指令

1:编写源码

2:javap解释整理字节码

3:通过jclasslib查看字节码指令

二:字节码分析

1:最全字节码指令分析

2:面试题


一: 操作数栈字节码指令

1:编写源码

public class OperandStackTest {
    public void testAndOperation(){
        byte i = 15;
        int j = 8;
        int k = i+j;
    }
}

2:javap解释整理字节码

        想要查看字节码文件呢,我们有两种方式,第一种就是直接进行javap,第二种就是使用jclasslib进行查看,我们先使用第一种。

PS D:\code\study\hadoop\shit\target\classes> javap -verbose .\OperandStackTest.class
Classfile /D:/code/study/hadoop/shit/target/classes/OperandStackTest.class
  Last modified 2023年11月9日; size 421 bytes
  SHA-256 checksum 487149a1edc4d19af0b1fe2369086c27c8765ff5e011491d1028d4f6cf1d9746
  Compiled from "OperandStackTest.java"
public class OperandStackTest
  minor version: 0
  major version: 52
  flags: (0x0021) ACC_PUBLIC, ACC_SUPER
  this_class: #2                          // OperandStackTest
  super_class: #3                         // java/lang/Object
  interfaces: 0, fields: 0, methods: 2, attributes: 1
Constant pool:
   #1 = Methodref          #3.#19         // java/lang/Object."<init>":()V
   #2 = Class              #20            // OperandStackTest
   #3 = Class              #21            // java/lang/Object
   #4 = Utf8               <init>
   #5 = Utf8               ()V
   #6 = Utf8               Code
   #7 = Utf8               LineNumberTable
   #8 = Utf8               LocalVariableTable
   #9 = Utf8               this
  #10 = Utf8               LOperandStackTest;
  #11 = Utf8               testAndOperation
  #12 = Utf8               i
  #13 = Utf8               B
  #14 = Utf8               j
  #15 = Utf8               I
  #16 = Utf8               k
  #17 = Utf8               SourceFile
  #18 = Utf8               OperandStackTest.java
  #19 = NameAndType        #4:#5          // "<init>":()V
  #20 = Utf8               OperandStackTest
  #21 = Utf8               java/lang/Object
{
  public OperandStackTest();
    descriptor: ()V
    flags: (0x0001) 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 1: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   LOperandStackTest;

  public void testAndOperation();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    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 3: 0
        line 4: 3
        line 5: 6
        line 6: 10
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      11     0  this   LOperandStackTest;
            3       8     1     i   B
            6       5     2     j   I
           10       1     3     k   I
}
SourceFile: "OperandStackTest.java"

3:通过jclasslib查看字节码指令

        首先进行recompile Java文件为字节码文件,然后我们在idea的view下找到这个:

        show ByteCode with JclassLib:

        最终显示结果如下:

二:字节码分析

1:最全字节码指令分析

public class OperandStackTest {
    public void testAndOperation(){
        byte i = 15;
        int j = 8;
        int k = i+j;
    }
}
 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

         bipush将15这个值push到了操作数栈中,此时我们的操作数栈就有了第一个值。我们需要回顾一下:byte、short、char、boolean、int类型在声明之后往数组中进行存放的时候都会保存为int类型。也就是说虽然定义的是byte类型,但是存放到数组中就是int类型

        栈帧在调用之初,栈帧被创建完成,其中的操作数栈和局部变量表是空的。PC寄存器中存放着第一条要执行的指令的地址。

        istore_1将这个值从操作数栈放到了局部变量表中索引为1的位置,为什么不是0呢?因为这不是一个静态方法,索引为零的位置存放的是this。

        此时的操作数栈就成了空,这是一个出栈的操作。过程中会修改PC寄存器中的索引值为下一条命令的索引值。

       过程中会修改PC寄存器中的索引值为下一条命令的索引值。

       同样的道理,8也会经过bipush和istore_2,然后最终的结果如下:

        iload_1和iload_2命令会将变量中索引为1,2的数据取出来分别放到局部变量表中

        最终的运行结果如下:

        紧接着会进行一个iadd命令,这个命令呢会使数据进行出栈,然后相加。值得注意的是,字节码指令需要被翻译为机器指令,机器指令操作CPU进行相加。然后将结果23放到操作数栈当中。

        运行结果如下:

        

        最终,istore_3将这个值从操作数栈放到了局部变量表中索引为3的位置, 此时的操作数栈就成了空,这是一个出栈的操作。过程中会修改PC寄存器中的索引值为下一条命令的索引值。

        最终的运行结果如下:

        我们也注意到,局部变量表长度为4,操作数栈深度为2(看javap的结果),这也是与图中可以对应上的,唯一区别的是局部变量表中的因为篇幅原因,this的位置也就是索引为0的变量槽没有展示出来。 

        补充说明:

        我们注意到bipush是将一个byte类型的数据push到操作数栈中基于int类型进行存储,还有sipush,这个字节码指令的含义是将short类型的数据push到操作数栈中基于int类型进行存储。

        如果方法有返回值,那么最终的字节码指令将由return会变成ireturn。也就是将值做了一个返回,这个栈帧就结束了,另外一个调用此方法的栈帧会立即调用一个aload_x这样的一个操作,将上一个方法的返回值加载到此栈帧的操作数栈中。

    public int getSum(){
        int m = 10;
        int n = 20;
        int k = m+n;
        return k;
    }

    public void testGetSum(){
        //aload_0获取上一个栈帧返回的结果,并保存在操作数栈中。
        int i = getSum();
        int j = 10;
    }

2:面试题

        i++ 和 ++j的区别是什么?

       此问题,后续我们在字节码文章中会跟大家进行探讨

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【无代码】【VR开发】【Unity】【VRTK】4-导入VRTK Tilia Package

【导入VRTK V4】 VRTK的Tilia Package包含了一整套空间开发方案。导入后你可以在PackageManager中看到它们。 所有的Tilia包都可以在如下页面找到: https://www.vrtk.io/tilia.html Tilia包有一个安装器,可以让你仅仅安装需要的包。包的种类很多,按照适用方向分类。 点击H…

C++ 之多态(一)

什么是虚函数 在类的定义中&#xff0c;前面有 virtual 关键字的成员函数称为虚函数&#xff1b;virtual 关键字只用在类定义里的函数声明中&#xff0c;写函数体时不用。 class Base {virtual int Fun() ; // 虚函数 };int Base::Fun() // virtual 字段不用在函数体时定义 …

react 实现chatGPT的打印机效果 兼容富文本,附git地址

1、方式一 &#xff1a;使用插件 typed.js typed.js 网站地址&#xff0c;点我打开 1.1、核心代码如下&#xff1a; //TypeWriteEffect/index.tsx 组件 import React, { useEffect, useRef } from react; import Typed from typed.js; import { PropsType } from ./index.d;…

t2017递推3骨牌

答案&#xff1a; #include<iostream> using namespace std; long long n,s[10009]; int main() {cin>>n;s[1]1,s[2]2,s[3]4;if(n1){cout<<1;return 0;}if(n2){cout<<2;return 0;}if(n3){cout<<4;return 0;}for(int i4;i<n;i)s[i]s[i-1]s[i…

什么是观察者模式?用 Python 如何实现 Observer(观察者或发布订阅)对象行为型模式?

什么是观察者模式&#xff1f; 观察者模式&#xff08;Observer pattern&#xff09;是一种行为型设计模式&#xff0c;它允许对象之间建立一种一对多的依赖关系&#xff0c;当一个对象的状态发生变化时&#xff0c;其相关依赖对象都会得到通知并自动更新。 在观察者模式中&am…

【服务发现与配置】Consul特性及搭建

文章目录 一、前言二、概念2.1、什么是Consul&#xff1f;2.2、Consul具有哪些特点?2.3、Consul 架构图2.4、Consul的使用场景 三、安装3.1. 下载3.2. 解压3.3. 拷贝到usr目录下3.4. 查看 安装是否成功3.5. 启动 四、Consul 开机自启动4.1. 路径/usr/lib/systemd/system/&…

【Qt之QMetaType】使用

介绍 QMetaType类管理元对象系统中的命名类型。 该类用作QVariant和排队的信号与槽连接中类型的编组辅助器。它将类型名称与类型关联起来&#xff0c;以便可以在运行时动态创建和销毁它。使用Q_DECLARE_METATYPE()声明新类型&#xff0c;以使它们可供QVariant和其他基于模板的…

三菱FX3U系列—原点回归指令

目录 一、简介 二、指令形式 1、原点指令[ZRN/DZRN] 2、带搜索的原点回归指令[DSZR] 三、回归指令运行过程 1、ZRN原点回归运行过程 2、带搜索的原点回归运行过程 四、特殊辅助继电器 五、特殊输出模块 六、总结 一、简介 用于将电机或伺服驱动器控制的轴回到预定的原…

浙江大学漏洞报送证书

获取来源&#xff1a;edusrc&#xff08;教育漏洞报告平台&#xff09; url&#xff1a;主页 | 教育漏洞报告平台 兑换价格&#xff1a;20金币 获取条件&#xff1a;提交浙江大学任意中危或以上级别漏洞

socks5代理和https代理有什么不同?各自有哪些优点?

socks5代理和https代理是两种不同的代理服务&#xff0c;它们在实现方式、安全性和协议特点等方面存在差异。下面我们来详细了解一下这两种代理的优点。 一、socks5代理的优点 1. 速度快 socks5代理采用了TCP协议&#xff0c;能够有效地减少网络延迟和数据传输速度慢的问题&…

Ubuntu22.04下挂载共享文件夹

1.在自己Windows任意地方建一个文件夹 2.打开虚拟机做如下配置 3.开启虚拟机&#xff0c;打开终端 4.输入&#xff1a;vmware-hgfsclient 看到物理机共享文件夹 5.输入&#xff1a;sudo mkdir /mnt/hgfs 创建虚拟机中的共享文件夹 6.输入&#xff1a;sudo vmhgfs-fuse .h…

离散数学第一章知识点复习

命题&#xff1a;陈述句 真值已经确定 原子命题&#xff08;简单命题&#xff09;&#xff1a;不能被分解为更简单的命题 命题化的时候的解题步骤&#xff1a; 1. 先给出原子命题 2. 符号化 注意蕴含式&#xff1a;记作 p -> q &#xff0c;p是前件&#xff0c;q 是后…

软件版本控制系统VCS工具——cvs vss svn git

版本控制 版本控制系统&#xff08;Version Control System&#xff0c;VCS&#xff09;是用于跟踪和管理源代码和文档的工具。可追踪和管理修改历史&#xff0c;包括修改的内容、时间、作者等信息。有助于团队协作、追踪变更、恢复历史版本等。VCS的主要目的是帮助团队协作开…

如何写一篇吊炸天的竞品分析

这段时间&#xff0c;除了撩妹之外&#xff0c;最多的就是竞品分析了。最近很多临近毕业的同学也在四处应聘产品岗&#xff0c;而一份不错的竞品分析一定能为你的求职加分不少。于是&#xff0c;有着菩萨心肠天使面孔魔鬼身材的我&#xff0c;就来教大家怎么做一份完整的竞品分…

什么是代理IP池?真实测评IP代理商的IP池是否真实?

代理池充当多个代理服务器的存储库&#xff0c;提供在线安全和匿名层。代理池允许用户抓取数据、访问受限制的内容以及执行其他在线任务&#xff0c;而无需担心被检测或阻止的风险。代理池为各种在线活动&#xff08;例如网页抓取、安全浏览等&#xff09;提高后勤保障。 读完…

【Bug】Python利用matplotlib绘图无法显示中文解决办法

一&#xff0c;问题描述 当利用matplotlib进行图形绘制时&#xff0c;图表标题&#xff0c;坐标轴&#xff0c;标签中文无法显示&#xff0c;显示为方框&#xff0c;并报错 运行窗口报错&#xff1a; 这是中文字体格式未导入的缘故。 二&#xff0c;解决方案 在代码import部…

将 Figma 轻松转换为 Sketch 的免费方法

最近浏览网站的时候&#xff0c;发现很多人不知道Figma是怎么转Sketch的。众所周知&#xff0c;Figma支持Sketch文件的导入&#xff0c;但不支持Sketch的导出&#xff0c;那么Figma是如何转Sketch的呢&#xff1f;不用担心&#xff0c;建议使用神器即时设计。它是一个可以实现在…

systemctl enable docker.service报错“Failed to execute operation: Bad message“

将docker加入到开机自启&#xff0c;报错&#xff1a; 解决&#xff1a; 重新粘贴复制&#xff1a; [Unit] DescriptionDocker Application Container Engine Documentationhttps://docs.docker.com Afternetwork-online.target firewalld.service Wantsnetwork-online.target…

在现实生活中传感器GV-H130/GV-21的使用

今天&#xff0c;收获了传感器GV-H130/GV-21&#xff0c;调试探头的用法&#xff0c;下面就来看看吧&#xff01;如有不妥欢迎指正&#xff01;&#xff01;&#xff01;&#xff01; 目录 传感器GV-H130/GV-21外观 传感器调试探头 探头与必要准备工作 传感器数值更改调试 …

Fabric: 使用InvokeChaincode实现跨通道数据访问

因为工作中遇到一些问题考虑使用Fabric的跨通道链码调用方法InvokeChaincode()来解决&#xff0c;这篇文章主要是记录以下在Fabric测试网络中InvokeChaincode()的使用过程及遇到的问题。 1 前期准备 1.1 认识InvokeChaincode InvokeChaincode的作用是调用指定的链码。而被调用…