为什么 JVM 叫做基于栈的 RISC 虚拟机?

news2024/11/17 7:24:12

为什么 JVM 叫做基于栈的 RISC 虚拟机?

其实这个问题比较简单,今天这篇文章的主要目的是想让大家看一下分析这个问题的逻辑,并且如何更好地从一手资料里寻找这些问题的答案。

上图是《深入理解 Java 虚拟机》一书中的截图。其实,说 JVM 是基于栈的虚拟机,指的是 JVM 所支持的指令集架构 ISA 是基于栈的,即字节码是基于栈的指令集架构。

有了指令集架构这层抽象,我们就无需关心其背后的实现是虚拟机还是物理机,甚至假如实际的执行是基于寄存器实现的,但指令集架构里是基于栈的,我们也可以说这套指令集架构是基于栈的。

指令集架构就是 ISA,Instruction Set Architecture。

我们通常使用的 Intel x86 CPU 的 ISA 可以查阅 Intel 手册第二部分。

这里按照首字母排序分成了三个部分进行逐一讲解,一共有几千条指令,所以是属于CISC 复杂指令集架构。

与之相对的精简指令集架构 RISC 的典型实现是 ARM,ARM 本身的指令集架构又分很多种,其中 A32 ISA 可以从官网下载到,指令数量仅有几百条,且指令长度均为 32 位,方便了指令译码与流水线优化。

而对于 JVM 这台虚拟计算机来说,字节码就是它的 ISA,它的官方手册就是:Java Language and Virtual Machine Specifications。

在 2.11 小节中给出了 ISA 的概述。

在后面的 Chapter 6 中列出了每一条字节码指令的详细说明和用法。

可以注意到,指令的数量非常少,且大部分是零地址指令,即指令长度大部分是固定的 1 字节,所以也是典型的 RISC 指令集架构。

字节码指令一共有多少个呢?看下 OpenJDK 源码里的 bytecodes.hpp,共 203 条指令。

而且,还有很多比如 iconst_0 iconst_1 iconst2 ... 这样的,在官方文档中是都归为一类的,所以实际上的指令数量更少,可以放心地把它归在精简指令集的类别里。

好了,我们现在解释清楚了,JVM 为什么是 RISC 指令集架构的虚拟机了。回顾一下我们的思考方式。

Intel x86 --> Intel 手册 --> CISC

ARM -> ARM A32 手册 --> RISC

JVM -> JVM 手册 --> RISC

嗯,完美!

接下来我们讨论,为什么 JVM 是基于栈的虚拟机

有两个关键点,一,基于栈说的是 ISA 是基于栈的,即字节码是基于栈的。二,既然说了基于栈,那与之相对的是什么呢?

我们两个问题一块来解释。

我们用 c 语言写一段简单的 1+1 程序。

int add() {
    int a = 1;
    int b = a + 1;
    return b;
}

它编译成 Intel x86 汇编是这样的。

add:
    pushl %ebp
    movl %esp,%ebp
    subl $8,%esp
    movl $1,-4(%ebp)
    movl -4(%ebp),%edx
    incl %edx
    movl %edx,-8(%ebp)
    movl -8(%ebp),%eax
    jmp .L1
.L1:
    leave
    ret

可以看出这里的 edx 寄存器就是作为计算 b 的结果的关键部件,所以 x86 ISA 是基于寄存器的。

如果我们用 java 语言编写这段程序。

public int add() {
    int a = 1;
    int b = a + 1;
    return b;
}

那么编译成给 JVM 看的 ISA 即字节码是这样的。

public int add();
  Code:
     0: iconst_1
     1: istore_1
     2: iload_1
     3: iconst_1
     4: iadd
     5: istore_2
     6: iload_2
     7: ireturn

这里面的 iload_1 iconst_1 和 iadd 都是使用操作数栈,所以字节码是基于栈的 ISA

这就把第二个问题讲清楚了,不需要其他多余的解释。

那具体的一条字节码指令在 CPU 中究竟是如何执行的呢?也是用栈来完成操作的么?

我们看其中一条指令 iconst_1。

根据 JVM 手册上的说明,该指令表示将 1 放入操作数栈顶。如果落实到 Intel x86 CPU 上也是使用栈来完成的操作,应该大概是 pushl $1 这种样子。

那实际上这条字节码指令在 Intel x86 上对应的指令是什么呢?

这里有两种不同的方式,第一种是比较古老的字节码解释器,通过纯软件来模拟字节码的行为,效率很低。

比如 iconst_1 会通过宏定义 SET_STACK_INT 来执行。

可以看到,实际上就是把数字 1 放入 topOfStack 数组中,这个数组就代表软件层面实现的 "操作数栈" 这个含义。

当然这种字节码解释器现在已经不用了,因为效率低下。

那么第二种实现方式就是模板解释器,即将每一个字节码指令和一个模板函数绑定,这个模板函数里会直接生成对应的机器码。

我们仍然使用 iconst_1 这个字节码来看。

我们看到,iconst_1 会执行到 templateTable 里面的函数,这里我们看 Intel x86 64 位机的实现,所以是 templateTable_x86_64.cpp 里。

如果立即数 value 为 0,也就是 iconst_0 指令将会生成 xorl 的机器码,即简单对寄存器进行清零操作。如果不为 0,那么将会生成 movl 的机器码。

继续往里跟进,会发现最终就是使用 emit_int 函数直接往内存地址处写二进制数值,这些数值就表示机器码了。

这里的 0xB8 是 x86 指令中的 Opcode 操作码,在 Intel 手册中可以看到,就是 mov 指令相关操作码的值。

在第一种字节码解释器中,iconst 会使用内存进行实现,可以理解为在软件层面真正实现了一个 "栈" 结构,即具体实现也是基于栈的。

但在模板解释器中,最终翻译成 x86 实现后仅仅只是寄存器操作,没有通过内存,即具体实现是基于寄存器的。

所以,虽然字节码这个 ISA 是基于栈来实现的,但具体在底层的实现是基于什么的,是不影响字节码是基于栈实现这个事实。

这时候我想搞怪一下,假如我把最终写入机器的这个机器码值给改了,那岂不是虚拟机就崩溃了?

我把刚刚那里的 0xB8 改成 0xAA,随便改个值,这么底层的位置,肯定会导致上面整座大厦都崩溃了。

重新编译 openjdk,最终输出下 java -version,果然 crash 了。

OK,全部问题就解释清楚了。我们通过对不同指令集的具体实现对比,分析出字节码是 RISC 指令集的一种。我们又通过字节码的官方手册,分析出字节码是基于栈实现的。

最后我们又通过剖析字节码在底层的执行引擎,分析出用软件实现一个基于栈的指令集,只要上层表现上是基于栈的,那么底层实现上可以很灵活。

这也体现了分层的好处,Java 程序员们只需要知道操作数栈,并且通过操作数栈来理解字节码的执行原理就可以了,而且这样理解对于 Java 语言层面,也算是十分 "底层" 了。

最最最后,我们又搞怪了一下,把 JVM 搞 crash 了,也因此验证了我们的结论。

本文的知识点不难,读过 JVM 相关原理的同学应该对这些概念已经熟悉了,但如何通过 一手资料 + 源码 + 分析推理 + 搞怪 的方式把这一切串联起来,是本文想表达给大家的,希望在这一点上对大家能有所启发。

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

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

相关文章

吊打面试官,HashMap 这一篇就够了

一、HashMap的简单使用 HashMap集合的创建&#xff1a; Map<String,String> map new HashMap<String,String>(); 使用put存储数据&#xff1a; map.put("张三","喜欢打游戏"); map.put("李四","喜欢睡觉"); map.put(…

电网运行信息检索系统的设计与实现

摘要 电网运行方式管理直接决定了电网企业的经济效益和安全效益,随着我国经济和社会的高速发展&#xff0c;我国电网的覆盖面积、网络节点和电压等级也高速增长。但是,我国当前电网运行方式管理工作水平还相对落后&#xff0c;制约了电网的安全经济效益。本文较为详细的分析了电…

第三章《数组与循环》第2节:多维数组

3.1小节介绍的数组都是把数组元素从逻辑上排成一行,因此它们被称为“一维数组”。如果一个班级内有15个学生,这些学生按照身高又分成3排就坐,其排列形式如图3-2所示: 3-2学生身高排列图 如果程序员希望按照每个学生在班级内的位置来存储他们的身高数据该怎么办呢?一些读者…

基于Java+Spring+Vue+elementUI大学生求职招聘系统详细设计实现

博主介绍&#xff1a;✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取联系&#x1f345;精彩专栏推荐订阅&#x1f447;&#x1f…

【项目设计】自主HTTP服务器

文章目录项目介绍网络协议栈介绍协议分层数据的封装与分用HTTP相关知识介绍HTTP的特点URL格式URI、URL、URNHTTP的协议格式HTTP的请求方法HTTP的状态码HTTP常见的HeaderCGI机制介绍CGI机制的概念CGI机制的实现步骤CGI机制的意义日志编写套接字相关代码编写HTTP服务器主体逻辑HT…

Windows AppData介绍

appdata是什么文件夹?&#xff08;应用程序数据&#xff09; 此文件夹是有关帐户信息、系统桌面、安装文件记录、快速启动文件夹等内容的。appdata下有三个子文件夹local&#xff0c;locallow&#xff0c;loaming。当你解压缩包时如果不指定路径&#xff0c;系统就把压缩包解到…

OpenCV图像处理——停车场车位识别

总目录 图像处理总目录←点击这里 十九、停车场车位识别 19.1、项目说明 唐宇迪老师的——OPENCV项目实战 学习 本项目的目的是设计一个停车场车位识别的系统&#xff0c;能够判断出当前停车场中哪些车位是空的。 任务共包含部分&#xff1a; 对图像预处理 从停车场的监控…

Vue基础之组件通信provide、inject

最近发现竟然还有小伙伴还不清楚provide、inject的用法&#xff0c;是时候普及一下provide、inject了&#xff1b; 常用的组件通信基本是父子组件通过props和emit来进行&#xff0c;一旦层级多了起来&#xff0c;props和emit就不好使了。每级都写props的话&#xff0c;会变得非…

PMP每日一练 | 考试不迷路-11.24(包含敏捷+多选)

11.27PMP考试倒计时 3天 每日5道PMP习题助大家上岸PMP&#xff01; ​题目1-2&#xff1a; ​1.在项目的规划阶段完成以后&#xff0c;但在正式执行之前&#xff0c;项目经理需要就项目目标进行沟通并获得承诺。项目经理下一步应该做什么? ( ) A.与所有相关方召开开工会议…

麻了,别再为难软件测试员了

前言 有不少技术友在测试群里讨论&#xff0c;近期的面试越来越难了&#xff0c;要背的八股文越来越多了,考察得越来越细&#xff0c;越来越底层&#xff0c;明摆着就是想让我们徒手造航母嘛&#xff01;实在是太为难我们这些测试工程师了。 这不&#xff0c;为了帮大家节约时…

深度操作系统20.5发布 deepin 20.5更新内容汇总

深度操作系统&#xff08;deepin&#xff09;是一款致力于为全球用户提供美观易用、安全稳定服务的Linux发行版&#xff0c;同时也一直是排名最高的来自中国团队研发的Linux发行版。深度操作系统20.5升级Stable内核至5.15.24&#xff0c;修复底层漏洞&#xff0c;进一步提升系统…

linux 清理垃圾文件

linux的文件系统比windows的要优秀&#xff0c;不会产生碎片&#xff0c;对于长时间运行的服务器来说尤为重要&#xff0c;而且linux系统本身也不会像windows一样产生大量的垃圾文件。不知道这个说法有没有可信度!至少我们可以确定的是linux系统的文件系统是比较优秀的! linux…

如何建立一个自己的网站?不懂代码搭建自己网站详细教程

搭建自己网站的准备&#xff1a; 1、首先需要注册购买一个域名&#xff0c;比如baidu.com&#xff0c;域名注册可以在阿里云或者其它域名注册平台注册。最常见的.com域名一般也就几十元一年&#xff1b; 域名 2、购买一个服务器&#xff0c;服务器也可以在阿里云或者景安等平…

数据结构之希尔排序

希尔排序 在插入排序的基础上&#xff0c;进行完善的算法 举个例子 如图我们把相距举例为4的两个元素组成一个子表 &#xff08;1和5&#xff0c;2和6&#xff0c;3和7&#xff0c;4和8&#xff09; 对各个子表进行直接插入排序 比如对子表2进行直接插入排序 13插入到38前&…

智慧小镇解决方案-最新全套文件

智慧小镇解决方案-最新全套文件一、建设背景二、建设思路三、建设方案四、获取 - 智慧小镇全套最新解决方案合集一、建设背景 智慧小镇&#xff0c;是指在城镇发展过程中&#xff0c;在城镇基础设施、资源环境、社会民生、经济产业、市政治理等领域中&#xff0c;充分利用物联…

2022亚太杯C题思路代码分析

C题就是数学比较开放的题目了&#xff0c;属于一个数据分析类题目&#xff0c;跟前两年的华为杯差不多&#xff0c;考察的也是全球变暖问题。更多内容文末名片查看 问题1.你同意有关全球气温的说法吗&#xff1f;使用2022_APMCM_C_Data。附件中的csv和其他您的团队收集的数据集…

用DIV+CSS制作四川成都美食网页介绍(网页设计期末课程设计)

家乡旅游景点网页作业制作 网页代码运用了DIV盒子的使用方法&#xff0c;如盒子的嵌套、浮动、margin、border、background等属性的使用&#xff0c;外部大盒子设定居中&#xff0c;内部左中右布局&#xff0c;下方横向浮动排列&#xff0c;大学学习的前端知识点和布局方式都有…

RetinaNet-Obj

真是东西多多每天都有新发现 论文地址&#xff1a;https://arxiv.org/abs/1908.09075 样本不平衡问题感觉近期研究的论文相对较多&#xff0c;如&#xff1a;2019 AAAI GHM&#xff0c;2019 CVPR AP-loss&#xff0c; 还有2019 DR loss&#xff0c; 2019 IoU-bala…

国外Essay写作怎么准确高效地审题?

Essay写作的重中之重是什么&#xff1f;毫无疑问肯定是审题审题还是审题&#xff0c;任何形式的Essay写作都以正确地审题为前提。小编就为大家分享如何准确而高效地审题。 What is the top priority of Essays writing?There is no doubt that it must be subject review or t…

python聚类分析如何可视化?

前言 聚类分析是一类将数据所对应的研究进行分类的统计方法。这一类方法的共同特点是&#xff0c;事先不知道类别的个数与结构&#xff1b;进行分析的数据是表明对象之间的相似性或相异性的数据&#xff0c;将这些数据看成对对象“距离”远近的一种度量&#xff0c;将距离近的…