a+b=c,处理器一步搞定,Java虚拟机为啥要四步?
基于栈的运行方式
Java虚拟机的执行过程基于字节码指令,可以将其视为对操作系统的一种抽象模拟。Java虚拟机具有自己的指令集和运行环境,包括堆(Heap)、栈(Stack)、方法区(Method Area)等。因此,Java虚拟机的指令操作流程与处理器的指令操作流程有许多相似之处,主要包括取指令、解码指令、执行指令以及更新计算等步骤。
Java虚拟机的指令集架构(Instruction Set Architecture,ISA)主要有两种实现方式:基于栈和基于寄存器。基于寄存器的指令集由于指令直接在寄存器中执行,因此执行效率较高。然而,由于寄存器是由硬件直接提供的,因此其数量和性能受到硬件的限制。
相比之下,基于栈的指令集的优点在于其高度的可移植性和相对容易的实现方式。寄存器的分配和管理是基于寄存器的指令集实现的一个主要难点。然而,基于栈的指令集的缺点是其执行速度相对较慢,这主要有两个原因:
1)基于栈的指令集需要维护出栈和入栈操作,这需要更多的指令,从而间接降低了执行效率。
2)基于栈的指令集的操作是对内存的访问,相比于处理器,内存的访问速度较慢。以下代码为例,来看两种指令集架构的差异:
int a = 1
int b = 2
int c = a + b
编译出来基于寄存器的指令:
add ax bx // AX寄存器的值为1,BX寄存器的值为2,将结果放入AX
编译出来基于栈的指令:
1 iload_0 // 操作数栈读取局部变量的第1个slot
2 iload_1 // 操作数栈读取局部变量的第2个slot
3 iadd // 将栈顶的两个slot相加
4 istore_2 // 保存到局部变量中第3个slot
栈架构的指令运算时是与操作数栈交互,即使是数据传递这样的简单操作。这样的好处就是可以忽视具体的物理架构。默认操作数存放在操作数栈上,运算后结果存放在栈顶,指令无需显式指定操作数的来源和去向。因此栈架构指令集的代码紧凑,一般都是一个或者两个字节,但所需的指令数量会比寄存器架构多。

栈的运行时
在Java虚拟机中,栈帧(Stack Frame)是一个关键的数据结构,用于支持方法的执行和方法之间的调用。每个栈帧由多个重要部分构成,包括局部变量表(Local Variable Table)、操作数栈(Operand Stack)、动态链接信息(Dynamic Linking)和方法返回地址(Return Address)。
局部变量表用于存储方法的参数以及方法内定义的局部变量。操作数栈则用于保存临时数据,特别是在执行算术运算或表达式时的中间计算结果。动态链接信息用于在方法调用过程中进行动态链接,这一机制是Java实现多态性(Polymorphism)的重要保障。方法返回地址则记录了方法执行完毕后,程序需要返回到的代码位置。
当方法被调用时,Java虚拟机会为该方法分配一个新的栈帧,并将其推入当前线程的栈顶。在方法执行过程中,虚拟机会根据字节码指令对操作数栈和局部变量表进行一系列操作,包括数据加载、存储、算术运算以及类型转换等。
当方法执行完成后,无论是正常退出还是由于未捕获的异常终止,Java虚拟机会将当前栈帧弹出,并将控制权转交给上一个栈帧,具体来说,是转交给方法返回地址所指定的位置。这个过程会持续进行,直到所有的栈帧都被弹出,标志着Java程序的执行结束。

操作数栈(Operand Stack),也被称为表达式栈(Expression Stack),是Java虚拟机执行计算的核心工作区域。它的深度是在编译期间通过代码分析计算出来的,并记录在方法的Code属性中。
操作数栈主要负责存储指令执行过程中的中间结果。几乎所有的字节码指令都会与操作数栈进行交互。例如,iadd 指令会从操作数栈顶弹出两个整数,相加后将结果压回操作数栈。这些中间结果可以是各种Java数据类型,包括基本类型(如 int, float, long, double)和对象引用(reference)。
此外,操作数栈还承担着在方法调用和返回过程中参数和返回值的传递任务。当方法被调用时,调用者方法计算出传递给被调用方法的参数值,并将这些参数值依次压入调用者自身的操作数栈。方法调用指令(如 invokevirtual, invokestatic)会消耗这些参数值,并将它们传递给被调用方法。在被调用方法的新栈帧中,这些参数值通常会从调用者的操作数栈转移到被调用方法栈帧的局部变量表中;当方法执行完毕并返回时,被调用方法将其计算得到的返回值(如果有)压入其自身的操作数栈顶。返回指令(如 ireturn, areturn)会将被调用方法栈帧的这个返回值弹出,并压入调用者方法的操作数栈顶,供调用者后续使用。
以下是一个简单的Java方法,以及对应的字节码指令,展示了操作数栈的使用:
public int add(int a, int b) {
return a + b;
}
对应的字节码指令(使用javap -c命令查看):
public int add(int, int);
Code:
0: iload_1 // 将局部变量表索引1处的值(即参数a)压入操作数栈
1: iload_2 // 将局部变量表索引2处的值(即参数b)压入操作数栈
2: iadd // 从操作数栈弹出两个int值,相加后将结果压入操作数栈
3: ireturn // 从操作数栈弹出顶部int值,作为方法的返回值
在上述字节码指令中,iload_1和iload_2指令将局部变量表中的值压入操作数栈,iadd指令从操作数栈弹出两个值进行相加操作,并将结果压回操作数栈,最后ireturn指令从操作数栈弹出顶部值作为方法的返回值。

未完待续
很高兴与你相遇!如果你喜欢本文内容,记得关注哦!!!
a+b=c,处理器一步搞定,Java虚拟机为啥要四步?的更多相关文章
- 【开源】简单4步搞定QQ登录,无需什么代码功底【无语言界限】
说17号发超简单的教程就17号,qq核审通过后就封装了这个,现在放出来~~ 这个是我封装的一个开源项目:https://github.com/dunitian/LoTQQLogin ————————— ...
- APP设计师拿到APP产品原型开始,七步搞定APP设计(转)
任何一款成功的APP都需要以坚实的产品概念作为基础,因为概念决定了产品最终完成的潜力. 一般情况下,交到app设计师手里的都是移动app产品原型图.当然这个是在移动产品经理反复斟酌,并且与大家开会讨论 ...
- iOS开发三步搞定百度推送
iOS开发三步搞定百度推送 百度推送很简单,准备工作:在百度云推送平台注册应用,上传证书. 步骤一: 百度云推送平台 http://push.baidu.com/sdk/push_client_s ...
- SmaterWeatherApi---签名加密和数据訪问--简单粗暴一步搞定
-----------------------------------------------------更新-2014-07-09---------------------------------- ...
- 破解jar包5步搞定,jira7.9.2操作成功,附github代码库
1,从要破解的程序中拷贝.jar包文件,运行1_jar.sh将其解压.以jira7.9.2为例: $install_dir\JIRA\atlassian-jira\WEB-INF\lib\atlass ...
- 轻松八步搞定Cacti配置安装(原创视频)
轻松八步搞定Cacti配置安装 1.安装web server $sudo apt-get install apache2 验证 http://localhost 2.$sudo apt-get ins ...
- Docker 一步搞定 ZooKeeper 集群的搭建
Docker 一步搞定 ZooKeeper 集群的搭建 背景 原来学习 ZK 时, 我是在本地搭建的伪集群, 虽然说使用起来没有什么问题, 但是总感觉部署起来有点麻烦. 刚好我发现了 ZK 已经有了 ...
- Java性能调优攻略全分享,5步搞定!(附超全技能图谱)
对于很多研发人员来说,Java 性能调优都是很头疼的问题,为什么这么说?如今,一个简单的系统就囊括了应用程序.数据库.容器.操作系统.网络等技术,线上一旦出现性能问题,就可能要你协调多方面组件去进行优 ...
- 五步搞定Android开发环境部署
引言 在windows安装Android的开发环境不简单也说不上算复杂,本文写给第一次想在自己Windows上建立Android开发环境投入 Android浪潮的朋友们,为了确保大家能顺利完成开发 ...
- 五步搞定Android开发环境部署——非常详细的Android开发环境搭建教程
在windows安装Android的开发环境不简单也说不上算复杂,本文写给第一次想在自己Windows上建立Android开发环境投入Android浪潮的朋友们,为了确保大家能顺利完成开发环境的搭 ...
随机推荐
- 基于.NetCore开发 StarBlog 番外篇 (4) 文章一键发布工具Publisher大升级,AI功能增强与界面优化
前言 自从上次开发了 StarBlogPublisher 这个文章创作神器之后 我的博客+公众号文章工作流效率提升了不少 不过这软件还有一些功能欠缺和我不满意的地方 这次就在这个下暴雨的周末,把这个软 ...
- AI+自动化测试系统方案:网络设备与网络应用智能测试
一.系统目标 通过AI与自动化测试工具的结合,实现网络设备和应用的 全生命周期测试,覆盖 流量分析.配置验证.故障排查.预警告警 四大核心场景,提升网络运维效率与可靠性. 二.技术架构设计 1. 整体 ...
- wireshark 抓包查看包得明文消息
转载注明出处: 最近在进行一些网络消息得定位,发现可以用wireshark查看网络包得消息内容,特此记录 需要注意得是,需要将wireshark更新到最新得版本,如果是老版本有可能不支持. 使用tcp ...
- 测试使用自己编译的WPF框架(本地nuget 包引用)
上一篇博客 本地编译WPF框架源码 - wuty007 - 博客园 说到自己在本地编译WPF 框架源码,并在本地 源码 的 \wpf\artifacts\packages\Debug\NonShipp ...
- L1-5、Prompt 写作中的常见误区
语言很自然,但写法要"工程化". 为什么要重视 Prompt 的写作规范? Prompt 是"给 AI 的任务指令",不清不楚,AI 就会"乱猜&qu ...
- 洛谷 P1416 攻击火星 排版重构
洛谷 P1416 攻击火星 原题P1416 Update 20210307 修复了挂掉的图片 20210307 重构排版 Solution understand 首先,你弄明白了什么是度吗? 一个点的 ...
- Springboot笔记<4>@Autowired和@Resource的区别
@Autowired和@Resource的区别 @Resource 有两个常用属性name.type,所以分4种情况 指定name和type:通过name找到唯一的bean,找不到抛出异常:如果typ ...
- k8s service访问偶发超时问题
问题现象 在某个集群节点上的服务访问service服务:端口,会出现偶发timeout的问题,集群有的节点不会出现访问timeout的问题 问题处理 查看bridge-nf-call-iptables ...
- 科学做Leetcode,拒绝思维懒惰
思考题目10分钟左右完全没有思路可以看题解,不要一道题自己整个30分钟,还是不会 => 这种行为属于思维上的懒惰,我们不要做一个懒惰的人 看题解: 10分钟左右完全没有思路看题解 做完题目一定要 ...
- 今天遇到了 X-Y PROBLEM
什么是X-Y 问题呢? 以下参考来自于耗子叔博客: 想解决问题X 他觉得Y可能是解决X的方法 但是他不知道Y应该怎么做 于是他去问别人Y应该怎么做? X-Y Problem 最大的严重问题就是:在一个 ...