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

news2024/11/16 9:58:01
概述
  • Java字节码对于虚拟机,好像汇编语言对于计算机,属于基本执行指令
  • Java虚拟机的指令由一个字节长度的,代表某种特定操作含义 的数字(称为操作码Opcode)以及跟随其后的零至多个代表此操作所需参数(操作数,Operands)而构成,由于Java虚拟机采用面向操作数栈而不是寄存器的结构,大多数指令都不包含操作数,只有一个操作码
  • 由于限制了Java虚拟机操作码的长度为一个字节(0-255),意味着指令集的操作码总数不可能超过256条
  • 熟悉虚拟机的指令对于动态字节码生成、反编译Class文件、Class文件修补都有着非常重要的价值。
执行模型
  • 如不考虑异常处理的话,那么Java虚拟机的解释器可以使用下面这个伪代码当做最基本的执行模型
do {
  自动计算PC寄存器的值加1;
  根据PC寄存器的指示位置,从字节码流中取出操作码;
  if(字节码存在操作数) 从字节码流中取出操作数;
  执行操作码所定义的操作;
} while(字节码长度>0);
字节码与数据类型
  • 在Java指令集中,大多数的指令都包含了其操作所对应的数据类型停止,如iload指令用于从局部变量表中加载int型的数据到操作数栈,而fload指令加载的则是float类型的数据
  • 对于大部分与数据类型相关的字节码指令,它们的操作码助记符中都有特殊的字符来表明专门为哪种数据类型服务
  • i代表int类型
  • l代表long
  • s代表short
  • b代表byte
  • c代表char
  • f代表float
  • d代表double
  • 也有一些指令的助记符中没有明确地指明操作类型的字母,如arraylength指令,它没有代表数据类型的特殊字符,但操作数永远只能是一个数据类型的对象
  • 无条件跳转指令goto则是与数据类型无关
  • 大部分的指令都没有支持整数类型byte,char和short,甚至没有任何指令支持boolean类型,编译器会在编译期或运行期将byte和short类型的数据带符号扩展为相应的int类型数据,将boolean和char类型数据零位扩展为相应的int类型数据,与之类似,在处理byte,char,boolean和short类型的数组时,也会转换为使用对应int类型的字节码指令来处理,
指令分类
  • 字节码指令集按用途分为9类
  • 加载与存储指令
  • 算术指令
  • 类型转换指令
  • 对象创建与返回指令
  • 方法调用与返回指令
  • 操作数栈管理指令
  • 比较控制指令
  • 异常处理指令
  • 同步控制指令
  • 在做值相关操作时
  • 一个指令,可以从局部变量表、常量池、堆中对象、方法调用、系统调用中等取得数据,这些数据被压入操作数栈
  • 一个指令,也可以从操作数栈中取出一到多个值(pop多次),完成赋值,加减乘除、方法传参、系统调用 等等操作
加载与存储指令
  • 作用:加载和存储指令用于将数据从栈帧的局部变量表和操作数栈之间来回传递
  • 常用指令
  • 再谈操作数栈与局部变量表
  • 局部变量压栈指令:将一个局部变量加载到操作数栈:xload、xload(x为i,l,f,d,a,n为0-3);xaload,xaload_(其中x为 i,l,f,d,a,b,c,s,n为0-3)
  • 常量入栈指令:将一个常量加载到操作数栈:bipush,sipush,ldc,ldc_w,ldc2_w,aconst_null,iconst_m1,iconst_,lconst_,fconst_,dconst_
  • 出栈装入局部变量表指令:将一个数值从操作数栈存储到局部变量表:xstore,xstore_(其中x为i,l,f,d,a,n为0-3);xastore(其中x为 i,l,f,d,a,b,c,s)
  • 扩展局部变量表的访问索引的指令:wide
  • 上面的指令助记符中,有一部分是以尖括号结尾的(iload_),这些助记符实际代表了一组指令(iload_代表iload_0,iload_1,iload_2,iload_3这几个指令),这几组指令都是带有一个操作数的通用指令的特殊形式,对于这若干组特殊指令来说,它们表面上没有操作数,不需要进行取操作数的动作,但操作数隐含在指令中
  • 除此之外,它们的语义与原生的通用指令完全一致(如iload_0的语义与操作数为0时的iload指令语义完全一致),在尖括号之间的字母指定了指令隐含操作数的数据类型,代表非负整数,代表是int类型数据,代表long类型,代表float,代表double类型
再谈操作数栈
  • Java字节码是Java虚拟机所使用的指令集,它与Java虚拟机基于栈的计算模型是密不可分的,在解释执行过程中,每当Java方法分配栈桢时,Java虚拟机往往需要开辟一块额外的空间作为操作数栈,来存放计算的操作数及返回结果
  • 具体来说,执行每一条指令之前,Java虚拟机要求该指令的操作数已经被压入操作数栈中,在执行指令时,Java虚拟机会将该指令所需的操作数弹出,并且将指令的结果重新压入栈中
    在这里插入图片描述
  • 以加法指令iadd为例,假设在执行该指令前,栈顶的两个元素分别为int值1和int值2,那么iadd指令将弹出两个int,并将求得的和int值3压入栈中
    在这里插入图片描述
  • 由于iadd指令只消耗栈顶的两个元素,因此,对于离栈顶距离为2的元素,即图中问号,iadd指令并不关心它是否存在,更加不会对其进行修改
  • 局部变量表(Local Variables)
  • Java方法栈帧的另一个重要组成部分是局部变量区,字节码程序可以将计算的结果缓存在局部变量区中
  • Java虚拟机将局部变量区当成一个数组,依次存放this指针(仅非静态方法),所传入的参数,以及字节码中的局部变量
  • 和操作数栈一样,long类型及double类型的值占用两个单元,其余类型占据一个单元
public void foo(long l,float f) {
  {
    int i = 0;
  }
  {
    String s = "Hello,World";
  }
}

在这里插入图片描述

  • 在栈帧中,与性能调优关系最为密切的部分就是局部变量表,局部变量表中的变量也是重要的垃圾回收根节点,只要被局部变量表中直接或间接引用的对象都不会被回收
  • 在方法执行时,虚拟机使用局部变量表完成方法传递
局部变量压栈指令

在这里插入图片描述

常量入栈指令
  • 常量入栈指令将常数压入操作数栈,根据数据类型和入栈内容的不同,分为const系统,push系列和ldc指令
  • 指令const系列 :用于特定的常量入栈,入栈的常量隐含在指令本身里,指令有:iconst_(i从-1到5)、lconst_(l从0到1)、fconst_(f从0到2)、dconst_(d从0到1)、aconst_null
  • 指令push系列:主要包括bipush和sipush,它们的区别在于接收数据类型的不同,bipush接收8位整数作为参数,sipush接收16位参数,它们都将参数压入栈
  • 指令ldc系列:如果以上指令不能满足需求,那么可以使用万能的ldc指令,它可以接收一个8位的参数,该参数指向常量池中的int、float或String的索引,将指定的内容入堆栈
  • ldc_w,接收两个8位参数,能支持的索引范围大于ldc
  • 如果压入的元素是long或者double类型的,则使用ldc2_w指令,使用方式类似
    在这里插入图片描述
    在这里插入图片描述
出栈装入局部变量表
  • 出栈装入局部变量表指令用于将操作数栈中栈顶元素弹出后,装入局部变量表的指定位置,用于给局部变量赋值
  • 这类指令主要以store的形式存在,比如xstore(x为i,l,f,d,a),xstore_n(x为i,l,f,d,a,n为0-3)
  • 其中,指令istore_n将从操作数栈中弹出一个整数,并把它赋值给局部变量索引n位置
  • 指令xstore由于没有隐含参数信息,故需提供一个byte类型的参数类指定目标局部变量表的位置
    注:
  • 类似像store这样的命令需要带一个参数,用来指明将弹出的元素放在局部变量表的第几个位置,但是,为了尽可能压缩指令大小,专门的istore_1指令表示将弹出的元素放置在局部变量表第1个位置,类似的还有istore_0,istore_1,istore_3,它们分别表示从操作数栈顶弹出一个元素,放在局部变量表第0,2,3个位置
  • 由于局部变量表前几个位置总是非常常用,因此这种做法虽然增加了指令数量,但是可以大大压缩生成的字节码的体积,如果局部变量表很大,需要存储的槽位大于3,那么使用istore指令,外加一个参数,用来表示需要存储的槽位位置。
    在这里插入图片描述
算术指令
  • 作用:算术指令用于对两个操作数栈上的值进行某种特定运算,并把结果重新压入操作数栈
  • 分类:
  • 对整型数据进行运算的指令
  • 对浮点类型数据进行运算的指令
  • byte,short,char,boolean类型说明
    在这里插入图片描述
  • 运算时的溢出
  • 数据运算可能会导致溢出,例如两个很大的正整数相加,结果可能是一个负数,Java虚拟机规范并无明确规定整数数据溢出的具体结果,仅规定了在处理整型数据时,只有除法指令以及求余指令中当出现除数为0时会导致虚拟机抛出异常ArithmeticException.
  • 运算模式
  • 向最接近数舍入模式:JVM要求在进行浮点数计算时,所有的运算结果都必须舍入到适当的精度,非精确结果必须舍入可被表示的最接近的精确值,如果有两种可表示的形式与该值一样接近,将优先选择最低有效位为零的
  • 向零舍入模式:将浮点数转换为整数时,采用该模式,该模式将在目标数值类型中选择一个最接近但是不大于原值的数字作为最精确的舍入结果
  • NaN值使用
  • 当一个操作产生溢出时,将会使用有符号的无穷大表示,如果某个操作结果没有明确的数学定义的话,将会使用NaN值来表示,而且所有使用NaN值作为操作数的算术操作,结果将返回NaN
public void method1() {
        int x = 10;
        int y = x / 0;
        System.out.println(y);   //java.lang.ArithmeticException: / by zero
        int i = 10;
        double j = i / 0.0;
        System.out.println(j);   //Infinity

        double d1 = 0.0;
        double d2 = d1 / 0.0;
        System.out.println(d2);  //NaN
    }
算术指令
  • 加法指令:iadd,ladd,fadd,dadd
  • 减法指令:isub,lsub,fsub,dsub
  • 乘法指令:imul,lmul,fmul,dmul
  • 除法指令:idiv,ldiv,fdiv,ddiv
  • 求余指令:irem,lrem,frem,drem //remainder:余数
  • 取反指令:ineg,lneg,fneg,dneg //negation:取反
  • 自增指令:iinc
  • 位运算指令
  • 位移指令:ishl,ishr,iushr,lshl,lshr,lushr
  • 按位与指令:iand land
  • 按位异或指令:ixor、lxor
  • 比较指令:dcmpg,dcmpl,fcmpg,fcmpl,lcmp
比较指令
  • 比较指令的作用是比较栈顶两个元素的大小,并将比较结果入栈
  • 比较指令有dcmpg,dcmpl,fcmpg,fcmpl,lcmp
  • 对于double和float类型的数字,由于NaN的存在,各有两个版本的比较指令,以float为例,fcmpg和fcmpl两个指令,它们的区别在于在数字比较时,若遇到NaN值,处理结果不同
  • 指令dcmpl和dcmpg也是类似的,根据其命名可以推测其含义
  • 指令lcmp针对long型整数,由于long整数没有NaN值,无需准备两套指令
    如:指令fcmpg和fcmpl都从栈中弹出两个操作数,并将它们做比较,设栈顶的元素为v2,栈顶顺位第2位的元素为v1,若v1=v2,则压入0,若v1>v2则压入1,若v1<v2则压入-1,两个指令不同之处在于,如遇到NaN值,fcmpg会压入1而fcmpl会压入-1
类型转换指令
  • 类型转换指令可以将两种不同的数值类型进行相互转换
  • 这些转换用于实现用户代码中的显示类型转换操作,或用来处理字节码指令中数据类型相关指令无法与数据类型一一对应的问题。
宽化类型转换(Widening Numeric Conversions)
  • 转换规则
  • 范围类型向大范围类型的安全转换,不需要指令执行
  • 从int到long,float或double类型,对应指令:i2l,i2f,i2d
  • 从long类型转换到folat或double类型,对应指令:l2f,l2d
  • 从float类型到double类型,对应指令f2d
  • 简化 : int > long > float > double
  • 精度损失问题
  • 宽化类型转换不会因为超过目标类型最大值而丢失信息,如从int到long,从int到double,不会丢失信息,转换后是精确相等的
  • 从int,long类型转float,或long转double时,将可能发生精度丢失–可能丢掉几个最低有效位上的值,转换后的浮点数值根据IEEE754最接近舍入模式所得到的正确整数值
@Test
    public void upcast2() {
        int i = 1223123123;
        float f = i;
        System.out.println(f);

        long l = 123123123123L;
        double d = l;
        System.out.println(d);

        long l1 = 123123123123123123L;
        double d1 = l1;
        System.out.println(d1);
    }
//执行结果---会出现精度损失
1.22312307E9
1.23123123123E11
1.2312312312312312E17
  • 尽管宽化类型转换实际上可能发生精度丢失,但这种转换永远不会导致Java虚拟机抛出运行时异常
  • 补充说明
  • 从byte,char和short转int类型的宽化类型转换实际是不存在的,对于byte转int,虚拟机并没有做实质性的转化处理,只是简单地通过操作数栈交换了两个数据,而将byte转long时,使用i2l,可以看到在内部byte等同于int类型处理,类似还有short
  • 这样处理一方面减少实际的数据类型,减少指令,目前虚拟机使用一个字节表示指令,因此指令总数不超过256个,为了节省资源,将short和byte当做int处理
  • 另一方面,由于局部变量表中的槽位固定为32位,无论是byte或者short存入局部变量表,都会占用32位空间,这个角度来说,没有必要特意区分这几种数据类型
//从下图中可以看出byte,short在执行类型转换时,转换为long使用i2l,转换为double使用i2d,转int时,什么都没做
public void upcast3(byte b) {
        int i = b;
        long l = b;
        double d = b;
    }
    public void upcast4(short s) {
        int i = s;
        long l = s;
        double d = s;
    }

在这里插入图片描述

 public void upcast1() {
        int i = 10;
        long l = i;
        float f = i;
        double d = i;
        float f1 = l;
        double d1 = l;
        double d2 = f1;
    }
//字节码如下
 0 bipush 10        //将10push到操作数栈
 2 istore_1        //将10存储到局部变量表1的位置
 3 iload_1        //从局部变量表1的值push到操作数栈
 4 i2l        //将操作数栈顶元素执行long的强制类型转换
 5 lstore_2   //将操作数栈顶的元素出栈放入到局部变量表2的位置
 6 iload_1
 7 i2f
 8 fstore 4
10 iload_1
11 i2d
12 dstore 5
14 lload_2
15 l2f
16 fstore 7
18 lload_2
19 l2d
20 dstore 8
22 fload 7
24 f2d
25 dstore 10
27 return
窄化类型转换
  • 转换规则
  • 从int到byte,short或char类型,对应指令:i2b,i2s,i2c
  • 从long类型转换到int类型,对应指令:l2i
  • 从float类型到int或long类型,对应指令f2i,f2l
  • 从double类型转换为int,long或float类型,对应指令d2i,d2l,d2f
  public void downcast1() {
        int i = 10;
        byte b = (byte) i;
        short s = (short) i;
        char c = (char) i;

        long l = 10L;
        int i1 = (int) l;
        byte b1 = (byte) l;       //转byte需要经过两条指令l2i,i2b,见下图
    }
    public void downcast2() {
        float f = 10;
        long l = (long) f;
        int i = (int) f;
        byte b = (byte) f;    
        
        double d = 10;
        byte b1 = (byte) d;     
    }

在这里插入图片描述

  • 精度损失问题
  • 窄化类型转换可能会导致转换结果具备不同的正负号、不同的数量级,因此,转换过程可能会导致数值丢失精度
  • 尽管数据类型窄化转换可能会发生上限溢出、下限溢出和精度丢失等情况,但是Java虚拟机规范中明确规定数值类型的窄化转换指令永远不会导致虚拟机抛出运行时异常
  • 补充说明
  • 当将一个浮点值窄化转换为整数类型T的时候,将遵循以下转换规则
  • 如果浮点值是NaN,那转换结果就是int或long的0
  • 如果浮点值不是无穷大的话,浮点值使用IEEE754的向零舍入模式取整,获得整数值v,如果v在目标类型T(int或long)表示的范围之内,那么转换结果就是V,否则,将根据V的符号,转换为T所能表示的最大或最小正数
  • 当一个double类型窄化转换为float类型时,遵循以下转换规则
  • 如果转换结果的绝对值太小而无法使用float来表示,将返回float类型的正负零
  • 如果转换结果的绝对值砂大,无法使用float来表示,将返回float类型 的正负无穷大
  • 对于double类型的NaN值将按规定转换为float类型的NaN值
 @Test
    public void downcast5() {
        double d1 = Double.NaN;
        int i = (int) d1;
        System.out.println(i);

        double d2 = Double.POSITIVE_INFINITY;
        long l = (long) d2;
        int j = (int) d2;
        System.out.println(l);
        System.out.println(Long.MAX_VALUE);
        System.out.println(j);
        System.out.println(Integer.MAX_VALUE);
        float f = (float) d2;
        System.out.println(f);
        float f1 = (float) d1;
        System.out.println(f1);
    }
//执行结果
0
9223372036854775807
9223372036854775807
2147483647
2147483647
Infinity
NaN

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

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

相关文章

Postman实现批量发送json请求

最近有一个场景&#xff0c;需要本地批量调用某个接口&#xff0c;从文件中读取每次请求的请求体&#xff0c;实现方法记录一下。 1.读取请求体 在 Postman 中&#xff0c;如果你想在 Pre-request Script 阶段读取文件内容&#xff0c;比如为了将文件内容作为请求的一部分发送…

电商api接口进行数据采集获取淘宝/天猫/京东/抖音多平台商品价格

在电商运营中&#xff0c;从品牌角度来看&#xff0c;品牌方通过电商数据采集API接口进行数据采集&#xff0c;获取多渠道商品价格信息的这一行为&#xff0c;能为品牌方带来诸多好处&#xff1a; 及时准确&#xff1a;API接口能为品牌提供实时数据&#xff0c;这意味着企业可…

北斗高精度定位终端的工作原理和精度范围

北斗高精度定位终端的工作原理主要基于北斗卫星导航系统&#xff0c;通过卫星信号的接收、处理和计算&#xff0c;实现了对目标位置的精确测量。以下是关于北斗高精度定位终端工作原理的引文&#xff1a; ​ 北斗高精度定位终端作为一款新型的高精定位设备&#xff0c;其核心…

Python自然语言处理(NLP)库之NLTK使用详解

概要 自然语言处理(NLP)是人工智能和计算机科学中的一个重要领域,涉及对人类语言的计算机理解和处理。Python的自然语言工具包(NLTK,Natural Language Toolkit)是一个功能强大的NLP库,提供了丰富的工具和数据集,帮助开发者进行各种NLP任务,如分词、词性标注、命名实体…

【全开源】简单商城系统源码(PC/UniAPP)

提供PC版本、UniAPP版本(高级授权)、支持多规格商品、优惠券、积分兑换、快递鸟电子面单、支持移动端样式、统计报表等 提供全部前后台无加密源代码、数据库离线部署。 构建您的在线商店的基石 一、引言&#xff1a;为什么选择简单商城系统源码&#xff1f; 在数字化时代&am…

ctfshow web 月饼杯II

web签到 <?php //Author:H3h3QAQ include "flag.php"; highlight_file(__FILE__); error_reporting(0); if (isset($_GET["YBB"])) {if (hash("md5", $_GET["YBB"]) $_GET["YBB"]) {echo "小伙子不错嘛&#xff…

图像分割模型LViT-- (Language meets Vision Transformer)

参考&#xff1a;LViT&#xff1a;语言与视觉Transformer在医学图像分割-CSDN博客 背景 标注成本过高而无法获得足够高质量标记数据医学文本注释被纳入以弥补图像数据的质量缺陷半监督学习&#xff1a;引导生成质量提高的伪标签医学图像中不同区域之间的边界往往是模糊的&…

数据复制的艺术:深拷贝与浅拷贝在JavaScript中的实现方式

前言 &#x1f4eb; 大家好&#xff0c;我是南木元元&#xff0c;热爱技术和分享&#xff0c;欢迎大家交流&#xff0c;一起学习进步&#xff01; &#x1f345; 个人主页&#xff1a;南木元元 目录 赋值和拷贝 浅拷贝与深拷贝区别 浅拷贝的实现方式 1.Object.assign() 2.…

6月来得及!考研数学120分复习规划:660/880/1000/1800怎么刷?

首先&#xff0c;120分是个什么概念&#xff1f; 如果目标120&#xff0c;历年真题就要135以上。这是因为&#xff1a; 1. 习题册里都是历年真题改编&#xff0c;很多题型见过了&#xff1b; 2. 考场发挥有不确定因素&#xff0c;所以需要安全边界。 总体规划 那么&#xff…

yolox-何为混合精度计算AMP?

何为AMP&#xff1f; 全称&#xff1a;Automatic mixed precision自动混合精度。 功能&#xff1a;在神经网络推理过程中&#xff0c;实现针对不同层采用不同的数据精度进行计算&#xff0c;从而实现节省显存和加速训练的目的。 此处提到的不同数据精度包括&#xff1a;32位浮…

SpringBoot搭建OAuth2

背景 前几天自己从零开始的搭建了CAS 服务器&#xff0c;结果差强人意&#xff08;反正是成功了&#xff09;。这几天&#xff0c;我躁动的心又开始压抑不住了&#xff0c;没错&#xff0c;我盯上OAuth2了&#xff0c;大佬们都说OAuth2比CAS牛批&#xff0c;我就想知道它有多牛…

FFmpeg编解码的那些事(1)

看了网上很多ffmpeg的编解码的文章和代码&#xff0c;发现有很多文章和代码都过时了&#xff0c;主要还是ffmpeg有很多接口都已经发生变化了。 这里简单说一下&#xff0c;什么是编码和解码。 1.视频编码 对于视频来说&#xff0c;可以理解为多张&#xff08;rgb或者yuv&…

【SCAU操作系统】实验四实现FCFS、SSTF、电梯LOOK和C-SCAN四种磁盘调度算法python源代码及实验报告参考

需求分析 设计一个程序将模拟实现FCFS&#xff08;先来先服务&#xff09;、SSTF&#xff08;最短寻道时间优先&#xff09;、电梯LOOK和C-SCAN&#xff08;循环扫描&#xff09;四种磁盘调度算法&#xff0c;并通过图形可视化界面动态展示每种算法的调度过程。 程序所能达到…

消费增值的真面目!绿色积分的合理运用!

各位朋友&#xff0c;大家好&#xff01;我是吴军&#xff0c;来自一家备受瞩目的软件开发企业&#xff0c;担任产品经理一职。今天&#xff0c;我非常荣幸能有机会与大家分享一种在市场上备受瞩目的新型商业模式——消费增值模式。 随着环保和可持续发展理念日益深入人心&…

网络、HTTP、HTTPS、Session、Cookie、UDP、TCP

OSI 七层模型 应用层、表示层、会话层、传输层、网络层、数据链路层、物理层 TCP/IP 五层模型 应用层&#xff1a;为用户的应用进程提供网络通信服务&#xff08;协议&#xff1a;域名系统DNS协议&#xff0c;HTTP协议&#xff0c;SMTP协议&#xff09;传输层&#xff1a;负…

Gopher的Rust第一课:第一个Rust程序

经过上一章[1]的学习&#xff0c;我想现在你已经成功安装好一个Rust开发环境了&#xff0c;是时候撸起袖子开始写Rust代码了&#xff01; 程序员这个历史并不算悠久的行当&#xff0c;却有着一个历史悠久的传统&#xff0c;那就是每种编程语言都将一个名为“hello, world”的示…

【渗透测试】|基于dvwa的CSRF初级,中级,高级

一、渗透测试 二、渗透测试过程中遇到的问题和解决 在初级csrf中&#xff0c;想要通过伪造一个404页面&#xff0c;达到修改密码的效果 伪造404页面的html代码如下&#xff1a; <html> <head> </head> <body> <img src"http://192.xx.xx.xx/…

python PyQt5 数字时钟程序

效果图&#xff1a; 概述 本文档将指导您如何使用Python的PyQt5库创建一个简单的时钟程序。该程序将显示当前时间&#xff0c;并具有以下特性&#xff1a; 始终在最前台显示。窗口可拖动。鼠标右键点击窗口可弹出退出菜单。时间标签具有红色渐变效果。窗口初始化时出现在屏幕…

解析智慧物流园区系统的多方位优势

智慧物流园区系统是基于物联网、大数据、人工智能等先进技术的应用系统&#xff0c;旨在实现物流园区的高效、智能化管理。随着物流行业的快速发展&#xff0c;传统物流园区已经无法满足日益增长的需求。智慧物流园区系统的出现填补了现有物流园区管理的空白&#xff0c;带来了…

Windows11系统安装QEMU虚拟化软件

Windows11系统安装QEMU虚拟化软件 QEMU软件是一个通用的开源机器模拟器和虚拟机。本文档适用于在Windows 11系统平台上安装QEMU软件。 1. 安装准备 1.1 安装平台 Windows 11 1.2. 软件信息 软件名称软件版本安装路径QEMUQEMU-8.2.93D:\qemu 1.3软件下载 QEMU官网官网下…