JVM学习-字节码指令集(二)

news2024/11/18 3:19:14
对象的创建与访问指令
创建指令
  • 虽然类实例和数组都是对象,但Java虚拟机对类实例和数组的创建和操作使用了不同的字节码指令
  • 创建类实例指令:new
  • 它接收一个操作数,指向常量池的索引,表示要创建的类型,执行完成后,将对象的引用压入操作数栈
  • 创建数组的指令
  • 创建数组的指令:newarray,arewarray,multianewarray
  • newarray:创建基本类型数组
  • anewarray:创建引用类型数组
  • multianewarray:创建多维数组
字段访问指令
  • 对象创建后,可能通过对象访问指令获得对象实例或数组实例中的字段或数组元素
  • 访问字段(static字段,或称为类变量)的指令:getstatic,putstatic
  • 访问类实例字段(非static字段,可实例变量):getfield,putfield
    如:以getstatic指令为例,它含有一个操作数,为指向常量池的Fieldref索引,它的作用是获取Fieldref指定的对象或者值,并将其压入操作数栈
public void sayHello() {
        System.out.println("hello");
    }
//对应字节码
0 getstatic #8 <java/lang/System.out>
3 ldc #9 <hello>
5 invokevirtual #10 <java/io/PrintStream.println>
8 return
数组操作指令
  • 数组操作指令主要有:xastore和xaload指令
  • 把一个数组元素加载到操作数栈的命令:baload,caload,saload,iaload,laload,faload,daload,aaload
  • 将一个操作数栈的值存储到数组元素中的指令:bastore,castore,sastore,iastore,lastore,fastore,dastore,aastore
    在这里插入图片描述
  • 取数组长度的指令:arraylength
  • 该指令弹出栈顶的数组元素,获取数组的长度,将长度压入栈
public void arrLength() {
        double[] arr = new double[10];
        System.out.println(arr.length);
    }
    //字节码
 0 bipush 10
 2 newarray 7 (double)
 4 astore_1
 5 getstatic #8 <java/lang/System.out>
 8 aload_1
 9 arraylength       //获取数组长度
10 invokevirtual #14 <java/io/PrintStream.println>
13 return
  • 说明
  • 指令xload表示将数组的元素压栈,如saload,caload表示压入short数组和char数组,指令xaload在执行时,要求操作数中栈顶元素为数组索引i,栈顶顺位第二个元素为数组引用a,该指令会弹出栈顶这两个元素,并将a[i]重新压入堆栈
  • xastore则专门针对数组操作,以iastore为例,它用于给一个int数组的给定索引赋值,在iastore执行前,操作数栈顶需要以此准备3个元素:值、索引、数组引用,istore会弹出这三个值,并将值败给数组中指定索引的位置
public void setArray() {
        int[] intArray = new int[10];
        intArray[3] = 20;
        System.out.println(intArray[1]);
    }
//字节码
 0 bipush 10
 2 newarray 10 (int)
 4 astore_1
 //----------------对应intArray[3] = 20
 5 aload_1           //数组地址
 6 iconst_3          //索引
 7 bipush 20         //值
 9 iastore
//----------------对应intArray[3] = 20
10 getstatic #8 <java/lang/System.out>
//----------------对应intArray[1]
13 aload_1        //数组地址
14 iconst_1       //数组索引
15 iaload
//----------------对应intArray[1]
16 invokevirtual #14 <java/io/PrintStream.println>
19 return
类型检查指令
  • 检查类实例或数组类型的指令:instanceof,checkcast
  • 指令checkcast用于检查类型强制转换是否可以进行,如果可以进行,那么checkcast指令不会改变操作数栈,否则它会抛出CassCastException异常
  • 指令instanceof用来判断是否是某一个类的实例,它会将判断结果压入操作数栈
public String checkCast(Object obj) {
        if (obj instanceof String) {
            return (String)obj;
        } else {
            return null;
        }
    }
//字节码指令
 0 aload_1
 1 instanceof #17 <java/lang/String>   //判断是否为String,即obj instanceof String
 4 ifeq 12 (+8)
 7 aload_1
 8 checkcast #17 <java/lang/String>       //强转
11 areturn
12 aconst_null
13 areturn
方法调用与返回指令
方法调用指令
  • 方法调用指令:invokevirtual,invokeinterface,invokespecial,invokestatic,invokedynamic
  • invokevirtual:用于调用对象的实例方法,根据对象的实际类型进行分派(虚方法分派),支持多态,是最常见的方法分派方式
  • invokeinterface:用于调用接口方法,它会在运行时搜索由特定对象所实现的这个接口方法,并找出适合的方法进行调用
//方法调用指令:invokeinterface
    public void invoke3() {
        Thread t1 = new Thread();
        ((Runnable)t1).run();
        Comparable<Integer> com = null;
        com.compareTo(123);
    }
  
//字节码
 0 new #4 <java/lang/Thread>
 3 dup
 4 invokespecial #5 <java/lang/Thread.<init>>
 7 astore_1
 8 aload_1
 9 invokeinterface #9 <java/lang/Runnable.run> count 1             //调用接口方法
14 aconst_null
15 astore_2
16 aload_2
17 bipush 123
19 invokestatic #10 <java/lang/Integer.valueOf>
22 invokeinterface #11 <java/lang/Comparable.compareTo> count 2
27 pop
28 return

在这里插入图片描述

  • invokespecial:调用一些特殊处理的实例方法,包含实例初始化方法(构造器),私有方法和父类方法,这些方法是静态类型绑定的,不会在调用时动态派发
//方法调用指令:invokespecial:静态分派
    public void invoke1() {
        //情况1:类实例构造器方法
        Date date = new Date();
        Thread t1 = new Thread();
        //情况2:调用父类方法
        super.toString();
        //情况3:私有方法
        methodPrivate();
    }

    private void methodPrivate() {}
//字节码指令
 0 new #2 <java/util/Date>
 3 dup
 4 invokespecial #3 <java/util/Date.<init>>
 7 astore_1
 8 new #4 <java/lang/Thread>
11 dup
12 invokespecial #5 <java/lang/Thread.<init>>        //构造器调用
15 astore_2
16 aload_0
17 invokespecial #6 <java/lang/Object.toString>        //父类方法调用
20 pop
21 aload_0
22 invokespecial #7 <com/chapter10/MethodInvokeReturnTest.methodPrivate>  //私有方法调用
25 return
  • invokestatic:调用命名类中的类方法(static方法),这是静态绑定的
//调用指令:invokestatic
    public void invoke2() {
        methodStatic();
    }

    public static void methodStatic() {}
//字节码
0 invokestatic #8 <com/chapter10/MethodInvokeReturnTest.methodStatic>
3 return
  • invokedynamic:调用动态绑定的方法,JDK1.7新加入的指令,用于在运行时动态解析出调用点限定符所引用的方法,并执行该方法,前4条调用指令的分派逻辑都固化在java虚拟机内部,而invokedynamic指令的分派逻辑是由用户所设定的引导方法决定的
方法返回指令
  • 方法调用结束前,需要进行返回,方法返回指令是根据返回值的类型区分的
  • 包括ireturn(boolan,byte,char,short和int类型使用),lreturn,freturn,dreturn和areturn
  • 还有一条return指令供声明为void的方法,实例初始化方法以及类和接口的类初始化方法使用
    在这里插入图片描述
  • 举例
  • 通过ireturn指令,将当前函数操作数栈的顶层元素弹出,并将这个元素压入调用者函数的操作数栈中,所有在当前函数操作数栈中的其他元素都会被丢弃
  • 如果当返回值是synchronized方法,那么还会执行一个隐含的monitorexit指令,退出临界区
  • 最后,会丢弃当前方法的整个帧,恢复调用者的帧,并将控制权转交给调用者
//方法返回指令
    public int returnInt() {
        int i = 200;
        return i;
    }
//字节码
0 sipush 200
3 istore_1
4 iload_1
5 ireturn
    public double returnDouble() {
        return 0.0;
    }
 //字节码
 0 dconst_0
1 dreturn
    public String returnString() {
        return "hello,world";
    }
//字节码
0 ldc #16 <hello,world>
2 areturn
    public int[] returnArr() {
        return null;
    }
        //字节码
    public float returnFloat() {
        int i = 10;
        return i;
    }
//字节码
0 bipush 10
2 istore_1
3 iload_1
4 i2f
5 freturn
    public byte returnByte() {
        return 0;
    }
//字节码
0 iconst_0
1 ireturn

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

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

相关文章

前端实习记录——git篇(一些问题与相关命令)

1、版本控制 &#xff08;1&#xff09;版本回滚 git log // 查看版本git reset --mixed HEAD^ // 回滚到修改状态&#xff0c;文件内容没有变化git reset --soft HEAD^ // 回滚暂存区&#xff0c;^的个数代表几个版本git reset --hard HEAD^ // 回滚到修改状态&#xff…

AI预测体彩排3采取888=3策略+和值012路一缩定乾坤测试5月29日预测第5弹

昨天的排三再次命中&#xff01;今天继续基于8883的大底进行测试&#xff0c;今天继续测试&#xff0c;好了&#xff0c;直接上结果吧~ 首先&#xff0c;888定位如下&#xff1a; 百位&#xff1a;6,7,5,8,4,9,1,0 十位&#xff1a;4,3,5,2,1,8,0,9 …

Kubernetes和Docker对不同OS和CPU架构的适配关系

Docker Docker官网对操作系统和CPU架构的适配关系图 对于其他发行版本&#xff0c;Docker官方表示没有测试或验证在相应衍生发行版本上的安装&#xff0c;并建议针对例如Debian、Ubuntu等衍生发行版本上使用官方的对应版本。 Kubernetes X86-64 ARM64 Debian系 √ √ Re…

操作系统真象还原:完善MBR

第3章-完善MBR 这是一个网站有所有小节的代码实现&#xff0c;同时也包含了Bochs等文件 编译器给程序中各符号&#xff08;变量名或函数名等&#xff09;分配的地址&#xff0c;就是各符号相对于文件开头的偏移量 。 section 称为节&#xff0c;在有的编译器中&#xff0c;同…

MSMG Toolkit深度Windows系统镜像文件个性定制!

MSMG Toolkit,这个听起来略显神秘的名字,在DIY电脑爱好者和系统管理员的圈子中却是大名鼎鼎。这是一款免费的系统定制工具,专为Windows操作系统量身定做,旨在帮助用户轻松移除不必要的系统组件、集成更新、添加驱动程序,以及实现无人值守安装等功能,让每一次系统安装都更…

raid配置与实战10

一、raid理论 1、raid概述 raid&#xff08;磁盘阵列&#xff09;&#xff1a;是用不同的硬盘分区&#xff0c;组成一个逻辑上的硬盘&#xff0c;高可用&#xff08;冗余&#xff09;。 2、raid级别 2.1、raid0条带化存储 数据分散在多个物理磁盘上的存储方式&#xff0c;…

layui实现表格根据数据来勾选已保存的数据

示例图 勾选一次保存后&#xff0c;每次进到查询都会看到被勾选的数据&#xff0c;代码如下&#xff1a; done: function(res, curr, count) {var groupId "[[${groupId}]]";$.ajax({url: //写后端获取数据的接口type: GET,success: function(data) {console.log(d…

登录安全分析报告:小米官网注册

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 暴力破解密码&#xff0c;造成用户信息泄露短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造成亏损无底洞 …

创建特定结构的二维数组:技巧与示例

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言&#xff1a;二维数组的奇妙世界 二、方法一&#xff1a;直接初始化 1. 初始化一个…

Chromium源码学习(1)—— 拉取源码,编译

阅读建议&#xff1a;先简单过一下整个文章目录结构&#xff0c;大致了解一下各个步骤在干什么&#xff0c;然后在上手操作可能会事半功倍。也许你遇到的有些问题文章中已经提及到了&#xff0c;但是由于你没有往下看导致卡进度。 Chromium简介 Chromium项目于2008年发布&…

CSS学习笔记:vw、vh实现移动端适配

移动端适配 移动端即手机端&#xff0c;也称M端 移动端适配&#xff1a;同一套移动端页面在不同屏幕尺寸的手机上可以实现宽度和高度的自适应&#xff0c;也就是页面中元素的宽度和高度可以根据屏幕尺寸的变化等比缩放 之前我在一篇博客中介绍了rem实现移动端适配&#xff0…

Linux内核编译流程3.10

一、内核源代码编译流程 编译环境&#xff1a; cat /etc/redhat-release CentOS Linux release 7.4.1708 (Core) Linux内核版本&#xff1a; uname -r 3.10.0-693.el7.x86_64 编译内核源代码版本&#xff1a;linux-4.19.90-all-arch-master cp /boot/config-xxx到内核源…

九章云极DataCanvas公司DingoDB完成中国信通院权威多模数据库测试

2024年5月16日&#xff0c;九章云极DataCanvas公司自主研发和设计的开源多模向量数据库DingoDB顺利完成中国信息通信研究院&#xff08;以下简称中国信通院&#xff09;多模数据库产品测试。本次测试的成功标志着DingoDB在技术能力、性能表现和产品稳定性方面得到了权威机构的高…

交互设计如何助力传统技艺在当代复兴?

背景介绍 榫卯是中国传统木工中一种独特的接合技术&#xff0c;它通过构件间的凸凹部分相互配合来实现两个或多个构件的紧密结合。这种结构方式不依赖于钉子或其他金属连接件&#xff0c;而是利用木材自身的特性&#xff0c;通过精巧的设计和工艺&#xff0c;实现构件间的稳定…

数据大屏方案 : 实现数据可视化的关键一环_光点科技

在数字时代的浪潮中&#xff0c;数据已经成为企业决策和操作的重要基础。因此&#xff0c;“数据大屏方案”逐渐成为业界关注的焦点。这类方案通过将复杂的数据集合以直观的形式展现出来&#xff0c;帮助决策者快速把握信息&#xff0c;做出更加明智的决策。 数据大屏的定义及作…

一年收入大几十个的副业兼职,闲鱼新玩法,新手小白可做,无门槛

在开始分享之前&#xff0c;我想先了解一下&#xff0c;大家是否曾在各大公众号上参与过各种打卡活动&#xff1f;比如减肥打卡、英语阅读打卡、考研考公打卡等等。如今&#xff0c;打卡已经成为现代人生活中不可或缺的一部分。无论是学习、健身还是工作&#xff0c;打卡都能有…

socks5 如何让dns不被污染

问题 发现firefox浏览器代理设置成socks5后&#xff0c;查看ip是成功了&#xff0c;但是谷歌等海外的还是无法正常访问。 原因 主要原因是socks5连接虽然是成功了&#xff0c;但是dns还是走国内的&#xff0c;国内的dns解析都被污染了导致没法正常访问 解决 把设置里的 使…

香橙派Kunpeng Pro评测

有幸受邀评测香橙派与华为鲲鹏在2024年5月12刚刚联合发布的新品香橙派Kunpeng Pro。 本文将从软硬件、AI算法测试等角度简单分享一下博主拿到板子以来感受与所做的评测。 一、硬件 香橙派Kunpeng Pro实物图 处理器方面&#xff0c;香橙派Kunpeng Pro采用了4核64位armv8架构处…

EthernetiP转modbusTCP网关在加氢催化中的应用

在现代工业控制系统中&#xff0c;Ethernet/IP和ModbusTCP是两种常见的通信协议。它们在各种设备和系统间传输数据&#xff0c;实现设备的监控和控制&#xff0c;尤其在催化加氢装置这类关键工业过程中发挥着不可或缺的作用。本文将深入探讨开疆智能KJ-EIP-206型Ethernet/IP转M…

探寻数据处理的高效之道:从Python内置方法到NumPy的飞跃

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言&#xff1a;为什么要学习NumPy&#xff1f; 二、案例展示&#xff1a;创建整数序列…