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

news2024/11/23 9:16:03

代码下载

操作数栈管理指令
  • 如同操作一个普通数据结构中的堆栈那样,JVM提供的操作数栈管理指令,可以用于直接操作数栈的指令
  • 将一个或两个元素从栈顶弹出,并且直接废弃:pop,pop2
  • 复制栈顶一个或两个数值并将复制值成双份的复制值重新压入栈顶:dup,dup2,dup_x1,dup_x1,dup_x2,dup_x2
  • 将栈最顶端的两个Slot数值位置交换,swap,Java虚拟机没有提供交换两个64位数据类型(long,double)数值的指令
  • 指令nop,是一个非常特殊指令,它的字节码为0x00。和汇编语言中的nop一样,表示什么都不做,这条指令一般可用于调试,占位等
  • 上述指令属于通用型,对栈的压入或弹出无需指明数据类型
  • 说明
  • 不带_x指令是复制栈顶数据并压入栈顶,包括两个指令,dup和dup2,dup的系数代表要复制的Slot个数
  • dup开头的指令用于复制1个Slot的数据,例如1个int可1个reference类型数据
  • dup2开头的指令用于复制2个Slot的数据,如1个long,2个int或1个int+1个float类型数据
  • 带_x的指令是复制栈顶数据并插入栈顶以下的某个位置,共有4个指令,dup_x1,dup_x1,dup_x2,dup_x2,对于带_x的复制插入指令,只要将指令的dup和x的系数相加,结果即为需要插入的位置,因此
  • dup_x1插入位置:1 + 1 = 2,即栈顶2个Slot下面
  • dup_x2插入位置:1 + 2 = 3,即栈顶3个Slot下面
  • dup2_x1插入位置:2 + 1 = 3,即栈顶3个Slot下面
  • dup2_x2插入位置:2 + 2 = 4,即栈顶4个Slot下面
  • pop:将栈顶的1个Slot数值出栈,如1个short类型数值
  • pop2:将栈顶的2个Slot数值出栈,如1个double类型数值,或2个int类型数值
//可以编译后,通过IDEA的jclasslib插件查看字节码
public class StackOperateTest {
    public void print() {
        Object obj = new Object();
        //String info = obj.toString();
        obj.toString();
    }
    public void foo() {
        bar();
    }
    public long bar() {
        return 0;
    }
    public long nextIndex() {
        return index ++;
    }
    private long index = 0;
}

控制转移指令
比较指令
  • 比较指令的作用是比较栈顶两个元素的大小,并将比较结果入栈
  • 比较指令有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
条件跳转指令
  • 条件跳转指令通常和比较指令结合使用,在条件跳转执行前,一般可以先用比较指令进行栈顶元素的准备,然后进行条件跳转

  • 条件跳转指令:ifeq,iflt,ifle,ifne,ifgt,ifge,ifnull,ifnonnull,这些指令都接收两个字节的操作数,用于跳转的位置(16位符号整数作为当前位置的offset)

  • 它们统一含义为:弹出栈顶元素,测试它是否满足某一条件,如果满足条件,则跳转到给定位置
    在这里插入图片描述

  • 注:

  • 对于boolan,byte,char,short类型的条件分支比较操作,都使用int类型比较指令完成
  • 对于long,float,double类型的条件分支比较操作,则会执行相应类型的比较运算指令,运算指令会返回一个整数值到操作数栈中,随后再执行int类型的条件分支比较操作来完成整个分支跳转
  • 由于各种类型的比较最终会转为int类型的比较操作,所以JVM提供的int类型的条件分支指令是最为丰富和强大的
比较条件跳转指令
  • 比较条件跳转指令类似于比较指令和条件跳转指令的结合体,它将比较和跳转两个步骤合二为一
  • 这类指令有if_icmpeq,if_icmpne,if_icmplt,if_icmpgt,if_icmple,if_icmpge,if_acmpeq和if_acmpne
  • 其中指令助词符加上"if_"后,以字符i开头的指令针对int型整数操作(包括short和byte类型),以字符a开头的指令表示对象引用的比较
    在这里插入图片描述
  • 这些指令都接收两个字节的操作数作为参数,用于计算跳转的位置,同时在执行指令时,栈顶需要准备两个元素进行比较,指令执行完成后,栈顶的这两个元素被清空,且没有任何数据入栈,如果预设条件成立,则执行跳转,否则,继续执行下一条语句
//可通过jclasslib插件查看字节码
 public void ifcompare1() {
        int i = 10;
        int j = 20;
        System.out.println(i < j);
    }
    public void ifcompare2() {
        short s1 = 9;
        byte b1 = 20;
        System.out.println(s1 > b1);
    }
    public void ifcompare3() {
        Object obj1 = new Object();
        Object obj2 = new Object();
        System.out.println(obj1 == obj2);
        System.out.println(obj1 != obj2);
    }
    //ifcompare3字节码
     0 new #10 <java/lang/Object>
 3 dup
 4 invokespecial #1 <java/lang/Object.<init>>
 7 astore_1
 8 new #10 <java/lang/Object>
11 dup
12 invokespecial #1 <java/lang/Object.<init>>
15 astore_2
16 getstatic #4 <java/lang/System.out>
19 aload_1
20 aload_2
21 if_acmpne 28 (+7)
24 iconst_1
25 goto 29 (+4)
28 iconst_0
29 invokevirtual #5 <java/io/PrintStream.println>
32 getstatic #4 <java/lang/System.out>
35 aload_1
36 aload_2
37 if_acmpeq 44 (+7)    //比较相等时跳转,见上图
40 iconst_1
41 goto 45 (+4)
44 iconst_0
45 invokevirtual #5 <java/io/PrintStream.println>
48 return
多条件分支跳转指令
  • 多条件分支跳转指令是专门为switch-case语句设计的,主要有tableswitch和lookupswitch
    在这里插入图片描述
  • tableswitch要求多个条件分支值是连续的,它内部只存放起始值和终止值,以及若干个跳转偏移量,通过给定的操作数index,可以立即定位到跳转偏移量位置,因此效率较高
  • lookupswitch内部存放着各个离散的case-offset对,每次执行都要搜索全部的case-offset对,找到匹配的case值,并根据对应的offset计算跳转地址,因此效率较低
  • 指令tableswitch的case是连续的,只需要记录最低值和最高值,以及每一个项对应的offset偏移量,根据给定index值通过简单计算可直接定位offset
public void switch1(int select) {
        int num;
        switch (select) {
            case 1:
                num = 10;
                break;
            case 2:
                num = 20;
                break;
            case 3:
                num = 30;
                break;
            default:
                num = 40;
        }
    }
//--字节码
 0 iload_1
 1 tableswitch 1 to 3	1:  28 (+27)    //switch... case 1-3
	2:  34 (+33)
	3:  40 (+39)
	default:  46 (+45)
28 bipush 10
30 istore_2
31 goto 49 (+18)
34 bipush 20
36 istore_2
37 goto 49 (+12)
40 bipush 30
42 istore_2
43 goto 49 (+6)
46 bipush 40
48 istore_2
49 return

public void switch2(int select) {
        int num;
        switch (select) {
            case 100:
                num = 10;
                break;
            case 500:
                num = 20;
                break;
            case 200:
                num = 30;
                break;
            default:
                num = 40;
        }
    }
    
//字节码
 0 iload_1
 1 lookupswitch 3
	100:  36 (+35)
	200:  48 (+47)
	500:  42 (+41)
	default:  54 (+53)
36 bipush 10
38 istore_2
39 goto 57 (+18)
42 bipush 20
44 istore_2
45 goto 57 (+12)
48 bipush 30
50 istore_2
51 goto 57 (+6)
54 bipush 40
56 istore_2
57 return
无条件跳转指令
  • 无条件跳转指令为goto,指令goto接收两个字节的操作数,共同组成一个带符号的整数,用于指定指令的偏移量,指令执行的目的就是跳转到偏移量给定的位置处
  • 如果指令偏移量太大,超过双字节的带符号整数的范围,则可以使用指令goto_w,它和goto有相同的作用,接收4个字节的操作数,可以表示更大的地址范围
  • 批评jsr,jsr_w,ret虽也是无条件跳转,但主要用于try-finally语句,且已经被虚拟机逐渐废弃,故不在这里介绍
    在这里插入图片描述

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

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

相关文章

【全开源】餐饮点餐系统源码(ThinkPHP+FastAdmin+UniApp)

开启智能餐饮新时代的钥匙 基于ThinkPHPFastAdminUniApp开发的餐饮点餐系统&#xff0c;主要应用于餐饮&#xff0c;例如早餐、面馆、快餐、零食小吃等快捷扫码点餐需求&#xff0c;标准版本仅支持先付款后就餐模式&#xff0c;高级版本支持先付后就餐和先就餐后付费两种模式。…

昆虫记思维导图,超详细解读

《昆虫记》是法国杰出昆虫学家、文学家法布尔的传世佳作&#xff0c;它不仅是一部研究昆虫的科学巨著&#xff0c;同时也是一部脍炙人口的文学经典。在这部作品中&#xff0c;法布尔以其独特的视角和细腻的笔触&#xff0c;为我们揭示了一个神秘而精彩的昆虫世界。那么&#xf…

重生之 SpringBoot3 入门保姆级学习(11、日志的进阶使用)

重生之 SpringBoot3 入门保姆级学习&#xff08;11、日志的进阶使用&#xff09; 3.2.4 文件输出3.2.5 日志文档的归档与切割 3.2.4 文件输出 配置 application.properties # 日志文件名 如果不写路径默认就是在项目根路径建立 demo.log 文件 推荐写法 D:\\demo.log 路径 文…

为什么要使用动态代理IP?

一、什么是动态代理IP&#xff1f; 动态代理IP是指利用代理服务器来转发网络请求&#xff0c;并通过不断更新IP地址来保护访问者的原始IP&#xff0c;从而达到匿名访问、保护隐私和提高访问安全性的目的。动态代理IP在多个领域中都有广泛的应用&#xff0c;能够帮助用户…

面试题:计算机网络中的七四五是什么?

面试题&#xff1a;计算机网络中的七四五是什么&#xff1f; 计算机网络中说的七四五是指&#xff1a;OSI 七层模型、TCP/IP 四层模型、OSI 与 TCP/IP 的综合五层模型 OSI 七层模型 OSI 将计算机网络分为了七层&#xff0c;每一层抽象底层的内容&#xff0c;并遵守一定的规则…

【错题集-编程题】过桥(BFS)

牛客对应题目链接&#xff1a;过桥 (nowcoder.com) 一、分析题目 类似层序遍历的思想。 二、代码 //值得学习的代码 #include <iostream>using namespace std;const int N 2010;int n; int arr[N];int bfs() {int left 1, right 1;int ret 0;while(left < right)…

PMP认证与NPDP认证哪个含金量高?

PMP和NPDP&#xff0c;哪个含金量更高呢&#xff1f; PMP可以全面提升你的职业发展&#xff0c;无论你是技术人员还是项目管理人员&#xff0c;都能帮助你打破思维定式&#xff0c;拓宽视野&#xff0c;并提升管理水平和领导能力。 NPDP不仅帮助个人了解新产品开发流程和原理…

分布式锁的原理和实现(Go)

文章目录 思维导图为什么需要分布式锁&#xff1f;go语言分布式锁的实现Redis自己的实现单元测试 红锁是什么别人的带红锁的实现 etcdzk的实现 面试问题什么是分布式锁&#xff1f;你用过分布式锁吗&#xff1f;你使用的分布式锁性能如何&#xff0c;可以优化吗&#xff1f;怎么…

为什么说OV SSL比DV SSL好

OV SSL证书和DV SSL证书是两种常见的SSL证书类型&#xff0c;它们在验证深度、安全性和可见性等方面存在差异。下面是具体分析&#xff1a; 验证深度 DV SSL&#xff1a;只进行域名所有权的验证。 OV SSL&#xff1a;除了验证域名所有权&#xff0c;还需要验证企业信息。 安…

2024年人文发展与社会科学国际会议(ICHDSS 2024)

2024年人文发展与社会科学国际会议 2024 International Conference on Humanities Development and Social Sciences 【1】会议简介 2024年人文发展与社会科学国际会议是一个汇集全球人文科学和社会科学领域专家学者的盛会。本次会议旨在深入探讨人文发展的多元性、复杂性以及社…

流媒体服务器SMS-语音对讲(一)

1.简介 在国标语音对讲对接中&#xff0c;会发现不同的厂商或不同型号的设备&#xff0c;对讲流程都不一样&#xff0c;本文主要介绍流媒体与设备之间的交互情况。 SMS流媒体服务代码库地址&#xff1a;https://gitee.com/inyeme/simple-media-server 2.流媒体与设备交互的可能…

【运维项目经历|025】企业高效邮件系统部署与运维项目

目录 项目名称 项目背景 项目目标 项目成果 我的角色与职责 我主要完成的工作内容 本次项目涉及的技术 本次项目遇到的问题与解决方法 本次项目中可能被面试官问到的问题 问题1&#xff1a;项目周期为多长时间&#xff1f; 问题2&#xff1a;服务器部署架构方式及数量…

【EI会议|稳定检索】2024年计算机科学与信号处理国际会议(CSSP 2024)

2024年计算机科学与信号处理国际会议&#xff08;CSSP 2024&#xff09; International Conference on Computer Science and Signal Processing in 2024 【大会信息】 大会地点&#xff1a;深圳 大会官网&#xff1a;http://www.iaccssp.com 投稿邮箱&#xff1a;iaccsspsub-…

丢失的数字 ---- 位运算

题目链接 题目: 分析: 解法一: 哈希表解法二: 高斯求和解法三:位运算 异或运算根据运算的性质, 相同的两个a异或 0 以示例一为例: 数组中有0,1,3, 缺失的数字是2, 那么只要我们将数组与0,1,2,3 异或, 就会得到2 代码: class Solution {public int missingNumber(int[] num…

CS的下载+内网穿透

CS的下载 纵向渗透&#xff1a;NC 瑞士军刀菜刀是一个hyyp协议 NC是TCP NC连接后没有任何回显 先受控房 nc.exe -l -p 12345 然后攻击方 nc.exe ip port 12345 扫描端口 上传和 nc.exe 同一目录下的文件 跳板机工具和NC的实际操作以及Termite联合管理 和nc是一样的…

ArcGIS教程(04):查找最近的消防站

本节目标 创建、设置和求解最近设施点分析。在本练习中&#xff0c;将查找可对给定地址处发生的火灾做出最快响应的四个消防站。还将生成消防队员的行进路线和驾车方向。 准备视图 双击打开【Exercise04.mxd】启用 【ArcGIS Network Analyst 扩展模块】单击【自定义 > 工…

DVWA靶场搭建:Apache、MySQL、PHP、DVWA

最近为了能够较为真实地学习Web渗透的各种技术&#xff0c;就想着自己搭建一个专门用于学习的Web演练平台--DVWA“靶场”。 DVWA可以进行暴力&#xff08;破解&#xff09;、命令行注入、跨站请求伪造、文件包含、文件上传、不安全的验证码、SQL注入、SQL盲注、弱会话ID、XSS漏…

解决docker容器: bash: ping: command not found, 并制作镜像

一. 出现原因 从 dockerhub 拉下来的镜像都是最轻量级的, 不会安装各种工具, 所以使用 ping, vim 等命令, 会出现 command not found 二. 解决方式 2.1 安装工具包 进入到一个正在运行的容器内部, 执行命令: apt-get update 之后会发现, 容器正在更新软件包, 不过最终会由…

(1+X)Java程序设计高级(一)

Throwable&#xff1a;异常的基类&#xff0c;所有异常都继承自 java.lang.Throwable 类&#xff0c;Throwable 类有两个直接子类&#xff1a;Error 类和 Exception 类。Error&#xff1a;是 Java 应用程序本身无法恢复的严重错误&#xff0c;应用程序不需要捕获、处理这些严重…

运筹学_2.线性规划

这里写目录标题 2.1 线性规划模型的建立线性规划定义线性规划模型建立的步骤 2.2 线性规划的标准型线性规划的一般形式线性规划的标准型线性规划的一般形式化为标准型方法 2.3 线性规划图解法2.4 线性规划问题的解可行解最优解基、基解、基可行解、可行基线性规划解的关系最优解…