《深入理解Java虚拟机》 JAVA 字节码指令 基础

news2024/11/18 16:31:42

1.操作数栈

解释时,JVM会为方法分配一个栈帧,而栈帧又由 局部变量表,操作数帧,方法引用,动态链接 组成

方法中的每条指令执行时,要求该指令的操作数已经压入栈中;执行指令时会将操作数从栈中弹出,是否将操作数再次压入栈中取决与具体的命令。

new,dup指令

使用new关键字创建对象的时候出现的字节码指令,通常伴随着 dup 指令 ,dup指令将复制一份操作数栈顶的值

这里是因为 invokespecial 调用类的构造方法时,将会消耗new的结果引用,如果我们不复制一份 ,那么这个引用就丢掉了。

public class ByteCodeDemo {

    public static void main(String[] args) {

        Object b = new Object();
    }
}

0 new #2 <java/lang/Object>
3 dup
4 invokespecial #1 <java/lang/Object.<init> : ()V>
7 astore_1
8 return

pop 指令

    public static void main(String[] args) throws InterruptedException {
        ByteCodeDemo byteCodeDemo = new ByteCodeDemo();
        byteCodeDemo.methodOne();

    }

    public  String methodOne(){
        return "no";
    }
  public static void main(java.lang.String[]) throws java.lang.InterruptedException;
    Code:
       0: new           #2                  // class com/sz/jasyptdemo/ByteCodeDemo
       3: dup
       4: invokespecial #3                  // Method "<init>":()V
       7: astore_1
       8: aload_1
       9: invokevirtual #4                  // Method methodOne:()Ljava/lang/String;
      12: pop
      13: return

调用了methodOne()方法,这个方法是有返回结果的,但是我们并没有接受 因此JVM会调用 pop指令,将返回值抛弃掉

iconst,bipush,sipush,ldc

iconst 表示加载一个常量,常量的值范围在 -1 ~5 之间,bipush 加载一个字节所能表示的int值,sipush加载两个字节所能表示的int值,ldc 则能加载任意值

    public static void main(String[] args) throws InterruptedException {
        int a = 5;
        int b = 6;
        int c = 129;
        int d = 32768;
    }
         0: iconst_5
         1: istore_1
         2: bipush        6
         4: istore_2
         5: sipush        129
         8: istore_3
         9: ldc           #2                  // int 32768
        11: istore        4
        13: return

img

Throwable

如果抛出异常,会将操作数栈清空,然后将异常实例压入操作数栈

2. 局部变量表 (数组)

加载与存储 load,store

Java 方法栈桢的另外一个重要组成部分则是局部变量区,字节码程序可以将计算的结果缓存在局部变量区之中。

Java 虚拟机将局部变量区当成一个数组,如果是实例方法,那么局部变量表这个数组的0号下标位置就是就是this指针,1号下标位置就是 参数,后面依次存放局部变量。

    public static void main(String[] args) throws InterruptedException {
        ByteCodeDemo byteCodeDemo = new ByteCodeDemo();
        byteCodeDemo.method(3);
    }

    public void method(int i){
        int a = 5;
        int b = 6;
        int c = 129;
        int d = 32768;
    }

对应的局部变量表

image-20230518203540998

因为调用的是实例方法,所以本地变量表序号0的位置上是 this指针,1号上是 方法参数 i,后面依次是方法从上往下的局部变量。

JVM对局部变量的主要有两组命令 加载 命令 load, 存储命令 sotre

   public static void main(String[] args) throws InterruptedException {
        ByteCodeDemo byteCodeDemo = new ByteCodeDemo();
        byteCodeDemo.method(3);
    }

    public void method(int i){
        int a = 5;
        int b = 6;
        int c = 129;
        int d = 32768;

        if (d<300){
            System.out.println("...");
        }
    }
 0 iconst_5
 1 istore_2
 2 bipush 6
 4 istore_3
 5 sipush 129
 8 istore 4
10 ldc #5 <32768>
12 istore 5
14 iload 5
16 sipush 300
19 if_icmpge 30 (+11)
22 getstatic #6 <java/lang/System.out : Ljava/io/PrintStream;>
25 ldc #7 <...>
27 invokevirtual #8 <java/io/PrintStream.println : (Ljava/lang/String;)V>
30 return

如上的字节码指令所示,首先是加载常量5到栈顶,然后调用 istore 将栈顶元素存储到局部变量表下标为2的位置上;然后调用bispush,将6压到栈顶… 然后调用iload指令 加载局部变量表下标为5的内容,与栈顶元素 300 比较,如果满足条件,往下执行;如果不满足,跳到偏移量为30的地方执行return返回;

不同基本数据的类型,有不同的load和store命令,如下图所示

img

通常对局部变量的操作是首先加载值然后压到操作数栈中进行计算,如下所示

    public void method(int i){
        int a = 5;
        int b = a+10;
        int c = 129;
        int d = 32768;


        if (d<300){
            System.out.println("...");
        }
    }
 0 iconst_5
 1 istore_2
 2 iload_2
 3 bipush 10
 5 iadd
 6 istore_3
 7 sipush 129
10 istore 4
12 ldc #5 <32768>
14 istore 5
16 iload 5
18 sipush 300
21 if_icmpge 32 (+11)
24 getstatic #6 <java/lang/System.out : Ljava/io/PrintStream;>
27 ldc #7 <...>
29 invokevirtual #8 <java/io/PrintStream.println : (Ljava/lang/String;)V>
32 return

如第2,3,5行指令所示;

但是也有指令能直接对局部变量表上的数值进行运算: 自增,自减操作

直接操作局部变量表的指令 iinc

    public void method(int i){
        int a = 1;
        int b = 10;

        a++;
        b--;
    }
 0 iconst_1
 1 istore_2
 2 bipush 10
 4 istore_3
 5 iinc 2 by 1
 8 iinc 3 by -1
11 return

如上字节码所示 iinc + 局部变量表的下标 + by + 增加的值

3. 其他指令

instanceof

后跟目标类,判断栈顶元素是否为目标类 / 接口的实例。是则压入 1,否则压入 0

    public void method(int i){
        Date date = new Date();
        if (date instanceof Object) {
            System.out.println("ofcause");
        }
    }
 0 new #5 <java/util/Date>
 3 dup
 4 invokespecial #6 <java/util/Date.<init> : ()V>
 7 astore_2
 8 aload_2
 9 instanceof #7 <java/lang/Object>
12 ifeq 23 (+11)
15 getstatic #8 <java/lang/System.out : Ljava/io/PrintStream;>
18 ldc #9 <ofcause>
20 invokevirtual #10 <java/io/PrintStream.println : (Ljava/lang/String;)V>
23 return

getstatic

访问静态字段,见上

monitorente monitorexit

为栈顶元素加锁和解锁

    public void method(int i){
      synchronized (new Object()){
          System.out.println("sync");
      }
    }

 0 new #5 <java/lang/Object>
 3 dup
 4 invokespecial #1 <java/lang/Object.<init> : ()V>
 7 dup
 8 astore_2
 9 monitorenter
10 getstatic #6 <java/lang/System.out : Ljava/io/PrintStream;>
13 ldc #7 <sync>
15 invokevirtual #8 <java/io/PrintStream.println : (Ljava/lang/String;)V>
18 aload_2
19 monitorexit
20 goto 28 (+8)
23 astore_3
24 aload_2
25 monitorexit
26 aload_3
27 athrow
28 return

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

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

相关文章

美团面试,被拷打了一小时....

刚从美团走出来&#xff0c;被拷打了一小时…越想越觉得可惜&#xff0c;回想面试经过&#xff0c;好好总结了几个点&#xff0c;发现面试没过的主要原因是在几个关键的问题没有给到面试官想要的答案。从而失去了这次宝贵的机会。 根据你的工作经历&#xff0c;说说你对质量保证…

python基础语法(print、数据类型、变量、注释、输入、条件语句)

一、初识编码&#xff08;密码本&#xff09; 计算机中所有的数据本质上都是用0和1的组合来存储的。编码就相当于密码本&#xff0c;在计算机中有多个密码本&#xff1a;utf-8编码、gbk编码等 注意事项&#xff1a;在计算机中若以某个编码形式进行保存文件&#xff0c;以后也…

ERP系统数据丢失的潜在经济损失

随着ERP系统的普及和涉及的范围越来越广&#xff0c;基本覆盖所有行业&#xff0c;ERP系统的数据安全也越来越被重视&#xff0c;关系到企业生命的机密信息都被存储在ERP系统中。 因此&#xff0c;ERP系统里存储的数据一旦泄露和丢失是一件非常可怕的事件。 那么&#xff0c;…

通俗易懂的教你如何使用Java实现快速排序

文章目录 快速排序&#x1f512;题目&#x1f4a1;分析&#x1f511;题解 快速排序 &#x1f512;题目 题目链接&#xff1a;785.快速排序-Acwing题库 &#x1f4a1;分析 基本思想&#xff1a;分治主要步骤 Step1&#xff1a;确定主元。从要划分的数组中选取一个元素作为主元…

python3+pytest+requests+allure+yaml测试框架搭建

目录 设计框架的原则 1.框架整体结构 2.框架各个模块说明 3.示例 3.1 先写一个测试用例 3.2 对上面的用例进行分层封装&#xff08;可根据业务复杂度分两层或者三层&#xff0c;此处演示分三层&#xff09; 3.3生成allure测试报告并查看 设计框架的原则 封装基类方法 对…

第十八章 使用LNMP架构部署动态网站环境

文章目录 第十八章 使用LNMP架构部署动态网站环境一、源码包程序1、源码包的优势2、基本步骤&#xff08;1&#xff09;、下载及解压源码包文件&#xff08;2&#xff09;、编译源码包代码&#xff08;3&#xff09;、生成二进制安装程序&#xff08;4&#xff09;、运行二进制…

VS2022调试Win-flex bison生成的C语言程序

Win-flex bison是flex和bison在Windows平台的一个移植版本&#xff0c;它支持flex&#xff08;快速词法分析器&#xff09;和bison&#xff08;GNU解析器生成器&#xff09;。 Win-flex bison的下载及安装可参看“Windows中使用Lex&#xff08;Win flex-bison&#xff09;”&a…

CIBF2023深圳电池展圆满结束!昂视期待与您下次相会

5月18日&#xff0c;CIBF2023深圳电池展圆满结束&#xff0c;展会为期三天&#xff0c;各位参展商展示了最新技术与产品&#xff0c;并在展位上开展花式互动&#xff0c;现场气氛火热。 作为电池行业的权威展会&#xff0c;CIBF2023深圳电池展为国内外用户、采购商、经销商提供…

cuda编程学习——第二个cuda程序(官方案例分析)!干货向(二)

前言&#xff1a; 最近在做三维重建&#xff0c;尤其是Nerf方面多视角合成工作的时候&#xff0c;意识到了cuda的编程计算可以大大提高其中渲染的计算&#xff0c;最明显的例子是Instant-ngp&#xff0c;Plenoxels等文章&#xff0c;因此后面会学Cuda一段时间&#xff0c;同时…

Python代码最好的加密.pyd——easycython(Windows系统)

1 安装easycython 1.1 建议选用python 3.6及其以下的版本&#xff01;&#xff01; 1.2 CMD命令行 pip install easycython2 安装Visual Studio 2.1 下载 点击链接 https://visualstudio.microsoft.com/zh-hans/free-developer-offers/ 2.2 安装注意事项 记得勾选红色下图的…

渗透测试--3.1.社会工程学攻击

目录 社会工程学攻击 SET介绍 一、建立克隆钓鱼网站收集目标凭证 二、set工具集之木马欺骗实战反弹链接 三、后渗透阶段 1.查看主机系统信息 2.到处用户密码的hash值 3.获得shell控制台 日志清除 四、钓鱼邮件 1、测试邮箱的连通性 2、参数说明 3、Kali 内置了s…

位运算实现加减乘除(自用水文)

目录 位运算实现加法 位运算实现减法 位运算实现乘法 位运算实现除法 代码示例 PS&#xff1a;用位运算实现的加减乘除&#xff0c;其数据都是整型的(int、char、size_t等&#xff09; 位运算实现加法 LeetCode_2.两数相加_小白麋鹿的博客-CSDN博客https://yt030917.blo…

【Jmeter第一章】Jmeter实操详细教程(快速入门)

文章目录 1、前言2、Jmeter介绍3、Jmeter下载安装4、Jmeter快速入门4.1、切换为中文显示4.2、基本使用 总结 1、前言 本篇内容为Jmeter的简单使用介绍&#xff0c;是基础的使用技巧&#xff0c;希望能帮到各位&#xff0c;不足之处还望多多包涵&#xff0c;最后感谢您的阅览。…

ChatGPT工作提效之初探路径独孤九剑遇强则强

ChatGPT工作提效之遇强则强 前言一、如何使用ChatGPT二、ChatGPT实战应用三、ChatGPT会叫的小孩有奶吃工具类的交互问答类的交互开发类的交互 前言 读《笑傲江湖》西湖比剑时&#xff0c;对于独孤九剑1的解读印象颇为深刻。令狐冲被任我行这个高手激发出许多精妙的剑招。这独孤…

【原创】企业级别的Kafka配置--按照市场分区

企业级别的Kafka配置--按照市场分区 背景--Kafka广播按照市场分区生产者和消费者设计方案Kafka Broker设计消费消息时增加过滤条件消费者端利用多线程/多协程机制提高吞吐量 背景–Kafka广播 对于同一个Topic来说&#xff0c;每个消费者组都可以拿到这个Topic中的全部数据。消…

论文阅读《Gradient-based Camera Exposure Control for Outdoor Mobile Platforms》

摘要 本文介绍了一种用于移动机器人平台上图像处理和计算机视觉应用的自动调节相机曝光的新方法。由于大多数图像处理算法严重依赖于主要基于局部梯度信息的低级图像特征&#xff0c;因此我们认为梯度量可以确定适当的曝光水平&#xff0c;从而使相机能够以对照明条件具有鲁棒…

LaTeX详细安装教程|LaTeX 基础知识|LaTeX 常用语法|LaTeX 快速入门

latex安装教程 一、LaTeX 基础知识1.1 LaTeX 的特点1.2 LaTeX 的基本组成部分 二、TeXLive安装包下载三、安装步骤四、TeXstudio安装及简单使用五、快速入门&#xff08;LaTeX 常用语法&#xff09;5.1 文本格式5.2 数学公式5.3 LaTeX 支持有序列表和无序列表5.4 图片和表格 La…

vim自动文件头

注意&#xff1a;以下方法是安装了ycm后的方法&#xff0c;没安装是否好使不知道&#xff0c;建议还是安装ycm&#xff0c;原版的vim真不好用。 在用vim编辑代码的时候自动添加文件头还是比较有用的。 比如像下面这样&#xff0c;只要输入vim test.py文件头就自动添加上了。 …

【Spring框架】--03.AOP

文章目录 5.面向切面&#xff1a;AOP5.1场景模拟5.1.1声明接口5.1.2创建实现类5.1.3创建带日志功能的实现类5.1.4提出问题 5.2代理模式5.2.1概念5.2.2静态代理5.2.3动态代理5.2.4测试 5.3AOP概念及相关术语5.3.1概述5.3.2相关术语①横切关注点②通知&#xff08;增强&#xff0…

微服务架构 云原生应用从这一步开始

什么是云原生应用和微服务架构 云原生应用是一种设计和构建方式&#xff0c;旨在充分利用云计算的弹性、可扩展性和高可用性特性。云原生应用将应用程序的开发、交付和运行环境与云平台密切结合&#xff0c;以实现高度灵活、可靠和可扩展的部署。 云原生应用的核心原则包括以…