首页 > 编程语言 >【15】Java字节码

【15】Java字节码

时间:2024-08-22 23:24:28浏览次数:11  
标签:操作数 15 字节 局部变量 指令 Java public

Java方法栈帧的组成:操作数栈+局部变量表

操作数栈

  • Java字节码是Java虚拟机所使用的的指令集。它与JVM基于栈的计算模型是分不开的。

  • 在解释执行过程中,每当为 Java 方法分配栈桢时,Java 虚拟机往往需要开辟一块额外的空间作为操作数栈,来存放计算的操作数以及返回结果。

    • 执行每条执行之前,JVM要求该指令的操作数已被压入操作数栈中
    • 在执行指令时,JVM会将该指令所需要的操作数弹出,并将该指令的结果重新压入栈中

以iadd为例说明该执行过程
在这里插入图片描述

  • 正常情况下,操作数栈的压入弹出都是一条条指令完成的
    在抛出异常时,JVM会清空操作数栈上到所有内容,而后将异常实例的引用压入操作数栈

直接作用在操作数栈上的Java字节码指令

dup 复制栈顶元素

dup指令常用于复制new指令生成的未经初始化的引用

  • 执行new指令时,JVM将指向一块已分配的但未初始化的内存引用压入操作数栈
  • invokespecial指令将要以这个引用为调用者,调用其构造器
    该指令将消耗操作数栈上的元素,作为它的调用者和参数
  • 这之前利用dup指令复制一份new指令的结果,并用来调用构造器
public void dup() {
    Object o = new Object();
}

// 对应的字节码
public void dup();
  descriptor: ()V
  flags: ACC_PUBLIC
  Code:
    stack=2, locals=2, args_size=1
       0: new               // class java/lang/Object
       3: dup
       4: invokespecial     // Method java/lang/Object."<init>":()V
       7: astore_1
       8: return
pop 舍弃栈顶元素

pop指令常用于舍弃调用指令的返回结果

  public static boolean bar() {
    return false;
  }

  public void foo() {
    bar();
  }
  // foo 方法对应的字节码如下:
  public void foo();
    0  invokestatic FooTest.bar() : boolean [24]
    3  pop
    4  return
invokestatic指令依然会将返回值压入pop方法的操作数栈
因此JVM需要执行额外的pop指令,将返回值舍弃
swap 交换栈顶两个元素的值

局部变量区

  • 字节码程序将计算的结果缓存在局部变量表
  • 局部变量表类似于一个数组,依次存放
    • this指针(针对实例方法)
    • 所传入的参数
    • 字节码中的局部变量
public void locals(long l, float f) {
    {
        int i = 0;
    }
    {
        String s = "Hello Word";
    }
}

// 对应的字节码
public void locals(long, float);
  descriptor: (JF)V
  flags: ACC_PUBLIC
  Code:
    stack=1, locals=5, args_size=3 //Java编译器在编译时就已经能确定操作数栈、局部变量表的大小以及参数个数(非static方法多一个this)
       0: iconst_0
       1: istore        4
       3: ldc               // String Hello Word
       5: astore        4
       7: return
       
1. locals是一个实例方法,局部变量表的第0个单元存放this指针
2. 第一个参数为long类型,占用局部变量表的第1、2个单元
3. 第二个参数为float类型,占用局部变量表的第3个单元
4. 方法体内的两个代码块中,分别定义了局部变量i和s,两者的生命周期没有重合,Java编译器将它们编排至同一单元,即局部变量表的第4个单元(istore 4和astore 4)
  • 存储在局部变量区的值,通常需要加载至操作数栈中,方能进行计算,得到计算结果后再存储至局部变量数组中。这些加载、存储指令是区分类型的。例如,int 类型的加载指令为 iload,存储指令为 istore。

综合示例

public static int bar(int i) {
  return ((i + 1) - 2) * 3 / 4;
}
// 对应的字节码如下:
Code:
  stack=2, locals=1, args_size=1 //Java编译器在编译时就已经能确定操作数栈、局部变量表的大小为1以及参数个数1个(static方法无this)
     0: iload_0
     1: iconst_1
     2: iadd
     3: iconst_2
     4: isub
     5: iconst_3
     6: imul
     7: iconst_4
     8: idiv
     9: ireturn

在这里插入图片描述

可以看到上图中最多使用了两个操作数栈

标签:操作数,15,字节,局部变量,指令,Java,public
From: https://blog.csdn.net/dyf4281/article/details/141404881

相关文章

  • Java学习笔记5—数据库日志文件
    1.slowlog慢SQL记录2.binlog*记录数据库执行的写操作(不包括查询)信息,以二进制的形式保存在磁盘中。使用场景:主从复制(在Master端开启binlog,然后将binlog发送到各个Slave端,Slave端重放binlog来达到主从数据一致。)和数据恢复(mysqlbinlog)binlog日志有三种格式,分......
  • HtmlUnit:自动化操作web页面的java工具
    java有httpclient等工具,可以模拟进行一些web操作,但一些逻辑是在前端js中执行的,此时httpclient就比较困难了。此时可以考虑使用HtmlUnit,模拟出一个浏览器,全程在浏览器中操作。 本文以在百度中输入搜索关键字->点击“百度一下”按钮->打印搜索结果这一过程为例,演示HtmlUnit的......
  • Javaweb+jsp外卖点餐系统+源码(三)
    第三章详细设计3.1 用户的主界面用户的主菜单界面。页面如图3-1所示:图3-1 用户的主界面3.2用户注册页面用户在首次登录外卖订餐系统管理页面时,需要在注册页面需要完成个人信息的注册。页面如图3-2所示:图3-2外卖订餐系统的注册页面3.3用户登录界面用户通......
  • 为什么java找工作难?java饱和了吗?
    在开始前我有一些资料,是我根据网友给的问题精心整理了一份「java的资料从专业入门到高级学习路线规划图」提升技术才是王道!限于文章篇幅原因,就不一一展示了,有需要的小伙伴扫码添加小助理获取!!24年初,当下java程序员的需求情况是,零项目经验的求职者难找工作,只能证明自己做过增......
  • JavaScript 的 标签
    标签标签在JavaScript中不是一个常见的特性,但在某些情况下,它们可以用于改善循环的可读性或退出嵌套循环。//使用标签来标识循环loop1:for(leti=0;i<10;i++){//循环1loop2:for(letj=0;j<10;j++){//循环2if(i===2&&j===2){......
  • CF1575G GCD Festival 题解
    考虑欧拉反演\[\sum\limits_{d\midn}\varphi(d)=n\]则原式可以化为\[\begin{align*}&\sum\limits_{i=1}^n\sum\limits_{j=1}^n\gcd(a_i,a_j)\cdot\gcd(i,j)\\=&\sum\limits_{i=1}^n\sum\limits_{j=1}^n\gcd(a_i,a_j)\sum\li......
  • JAVA IO流-小白版
    I/O流原理I/O是Input/Output的缩写,I/O流技术是非常实用的技术,用于处理数据传输。如读/写文件,网络通讯等;Java中对于数据的输入/输出操作以"流(stream)"的方式进行;Java.io包下提供了各种"流"类和接口,用以获取不同种类的数据,并通过方法输入或输出数据;输入input:读取外部......
  • 深入理解 Java 中 ArrayList 的底层原理
    在这篇博客中,我们将深入探讨ArrayList的底层实现原理,并通过逐步剖析ArrayList的源码来理解其内部工作机制。我们将重点关注ArrayList的创建、元素添加、扩容机制等关键点。创建ArrayList集合对象ArrayList<String>list=newArrayList<>();使用空参构造器创建ArrayList集合......
  • [Java手撕]线程安全的转账
    首先来看线程不安全的转账publicclassBank{privateint[]accounts;publicBank(){this.accounts=newint[10];for(inti=0;i<10;i++){accounts[i]=1000;}}publicvoidtransfer(intfrom,int......
  • 一起学Java(3)-Java项目构建工具Gradle和Maven场景定位和优缺点对比
    在第一步创建的项目(java-all-in-one)项目里,我们提到了使用Gradle作为项目构建工具。看到这里,不知道你是否有疑惑,什么是项目构建工具。Java项目常用构建工具有哪些?都有什么特点?带着疑惑,本文对Java的构建工具进行一些梳理,以同步理解。从而使大家对我们项目中使用到的技术栈和技术......