[转帖]【JVM】字节码执行引擎
引入
class文件就是字节码文件,是由虚拟机执行的文件。也就是java语言和C & C++语言的区别就是,整个编译执行过程多了一个虚拟机这一步。这个在 类文件结构 中已经解释。上一节讲了虚拟机是如何加载一个class的,这一节就讲解虚拟机是如何执行class文件的。
运行时栈帧结构
1.定义
栈是每个线程独有的内存。
栈帧存储了局部变量表,操作数栈,动态连接,和返回地址等。
每一个方法的执行 对应的一个栈帧在虚拟机里面从如栈到出栈的过程。
只有位于栈顶的栈帧才有有效的,对应的方法称为当前方法。
执行引擎运行的所有指令只针对当前栈帧和当前方法。
2.栈帧结构
每一个栈帧都包含了局部变量表、操作数栈、动态连接、方法返回地址和一些额外的附加信息。
在编译 程序代码的时候,栈帧中需要多大的局部变量表、多深的操作数栈都已经完全确定了,并且写入到方法表的Code属性之中,因此一个栈帧需要分配多少内存,不会受到程序运行期变量数据的影响,而仅仅取决于具体的虚拟机实现。
栈帧图解:
3.局部变量表
(1)定义:
局部变量表存放的一组变量的存储空间。存放方法参数和方法内部定义的局部变量表。
在java编译成class的时候,已经确定了局部变量表所需分配的最大容量。
局部变量表的最小单位是一个Slot。
虚拟机规范没有明确规定一个Slot占多少大小。只是规定,它可以放下boolean,byte,…reference &return address.
reference 是指一个对象实例的引用。关于reference的大小,目前没有明确的指定大小。但是我们可以理解为它就是类似C++中的指针。
局部变量表的读取方式是索引,从0开始。所以局部变量表可以简单理解为就是一个表.
(2)局部变量表的分配顺序如下:
this 引用(隐式参数)
方法的参数表。
根据局部变量顺序,分配Solt。
一个变量一个solt,64为的占2个solt。java中明确64位的是long & double
注意:局部变量只给予分配的内存,没有class对象的准备阶段,所以局部变量在使用前,必须先赋值(无初始值)。为了尽可能的节约局部变量表,Solt可以重用。
4.操作数栈
用来存放操作数的栈结构,当一个方法刚开始执行的时候,这个方法的操作数栈是空的,在方法的执行过程中,会有各种字节码指令向操作数栈中写入和提取内容,也就是入栈和出栈的操作。
注:java虚拟机的解释执行引擎称为基于栈的执行引擎,其中所指的栈就是操作数栈
5.动态连接
每个栈帧都包含一个指向运行时常量池的引用,持有这个引用是为了支持动态连接。
符号池的引用,有一部分是在第一次使用或者初始化的时候就确定下来,这个称为静态引用。
还有一部分是在每一次的运行期间转化为直接引用,这个就是动态连接
6.方法返回地址
(1)方法被执行后,有两种方式退出这个方法
- 执行引擎遇到任意一个方法的返回的字节码指令(如return)
- 在方法执行过程中遇到了异常,并且这个异常并没有在方法体中得到处理。
(2)方法退出之后,需要返回到方法被调用的位置,程序才能继续执行,方法返回时需要在栈帧中保存一些信息,用以帮助它恢复它上层方法的执行状态。一般情况下,调用者的pc计数器的值可以作为返回地址,栈帧中很可能会保存这个计数器值,方法异常退出时,返回地址是要通过异常处理器表来确定,栈帧中一般不会保存这部分信息。
(3)方法退出的过程实际上等同于把当前栈帧出栈,所以可能需要执行这些操作:恢复上层方法的局部变量表和操作数栈,把返回值压入调用者栈的操作数栈中,调整pc计数器的值。
注:附加信息:虚拟机规范允许具体的虚拟机实现增加一些规范里没有描述的信息到栈帧中,这部分信息取决于具体的虚拟机实现。
7.方法调用
(1)方法调用阶段的唯一任务就是确定被调用方法的版本(即调用哪一个方法),暂时不涉及方法内部的具体运行过程。
(2)class文件的编译过程中不包含传统编译中的连接步骤,一切方法调用在class文件中存储的都是符号引用,而不是方法在实际运行时内存布局中的入口地址,这使得java有着更强大的动态扩展能力,但也使得java方法的调用过程变得相对复杂起来,需要在类的加载甚至运行期间才能确定目标方法的直接引用。
(3)两种方法调用
解析调用:方法在程序真正运行之前就有一个可确定的调用版本,并且这个方法的调用版本在运行期是不可改变的
符合这个条件的有静态方法,私有方法,实例构造器和父类方法四类,它们在类加载的时候会把符号引用解析为该方法的直接引用。
解析调用一定是一个静态的过程,编译期间就完全确定,在类装载的解析阶段就会把涉及到的符号引用全部转化为可确定的直接引用,不会延迟到运行期间再去完成。
分派调用:可能是静态的也可能是动态的,根据分派依据的宗量数又可分为单分派和多分派。分派机制与java的多态机制关系密切。
静态分派:依赖静态类型来定位方法执行版本的分派动作。静态分派的最典型的应用就是方法重载。静态分派发生在编译阶段,因此确定静态分派的动作实际上不是由虚拟机来执行的
动态分派:在运行期间根据实际类型来确定方法执行版本的分派调用过程称为动态分派。这跟多态性的另一个体现——重写有着很密切的关联。
单分派:根据一个宗量对目标方法进行选择
多分派:根据多于一个的总量对目标方法进行选择。
常用字节码
字节码指令是一个byte整数
(1) 局部变量压栈
Xload(x为i l f d a) a表示object ref
Xload_n (n为 0 1 2 3)将第几个局部变量的值压栈
Xaload(x为i f l d a b c s)从数组中取得给定索引的值,将该值压栈
(2) 出栈装载入局部变量
Xstore (x为i l f d a)出栈,存入局部变量
Xstore_n(n为0 1 2 3)出栈,将值存入第n个局部变量
Xastore(x为i f l d a b c s)将值存入数组
(3) 通用栈操作(无类型)
Nop
Pop 弹出栈顶1个字长
Dup 复制栈顶一个字长,复制内容压栈
(4) 类型转化
I2l i2f l2i l2f l2d f2i f2d d2i d2l d2f i2b i2c i2s
i2l表示将int转为long
(5) 整数运算
- Iadd lsub idiv imul linc
(6) 浮点运算
- Fadd dadd fsub fdiv ddiv fmul dmul
(7) 对象操作指令
- New getfield putfield getstatic putstatic
(8) 条件控制
Ifeq 若为0,则跳转,
ifne 若不为0,则跳转
iflt 若小于0,则跳转,
ifge若大于0,则跳转
if_icmpeq 如果两个int相同,则跳转
(9) 方法调用
Invokevirtual
Invokespecial
Invokestatic
Invokeinterface
xreturn
(10) 常量入栈
Aconst_null null对象入栈
Iconst_m1 int常量-1入栈
Iconst_0 int常量0入栈
Lconst_1 long常量1入栈
Fconst_1 float常量1.0入栈
Dconst_1 double常量1.0入栈
Bipush 8位带符号整数入栈
Sipush 16位带符号整数入栈
Idc 常量池中的项入栈
说了这么多,下面来个例子实战一下
简单的字节码执行实例
例:Java程序
public class TestFile {
public int calc() {
int a = 500;
int b = 200;
int c = 50;
return (a + b) / c;
}
}
执行 javap –verbose TestFile 命令生成反汇编代码如下:
public int testfile();
Code:
Stack=2, Locals=4, Args_size=1
0: sipush 500
3: istore_1
4: sipush 200
7: istore_2
8: bipush 50
10: istore_3
11: iload_1
12: iload_2
13: iadd
14: iload_3
15: idiv
16: ireturn
}
执行过程
1.将500入栈,然后出栈将500存入第一个局部变量
2.将200入栈,然后出栈将200存入第二个局部变量
3.将50入栈,然后将50存入第三个局部变量
4.将第一个局部变量的值(500)压栈,然后将第二个局部变量的值(200)也压栈
5.执行整型加法运算,然后将第三个局部变量的值(50)压栈
6.执行整型除法运算,最后执行整型的返回操作将值返回。
本人才疏学浅,若有错,请指出,谢谢!
如果你有更好的建议,可以留言我们一起讨论,共同进步!
衷心的感谢您能耐心的读完本篇博文。
[转帖]【JVM】字节码执行引擎的更多相关文章
- JVM总结(五):JVM字节码执行引擎
JVM字节码执行引擎 运行时栈帧结构 局部变量表 操作数栈 动态连接 方法返回地址 附加信息 方法调用 解析 分派 –“重载”和“重写”的实现 静态分派 动态分派 单分派和多分派 JVM动态分派的实现 ...
- 一夜搞懂 | JVM 字节码执行引擎
前言 本文已经收录到我的 Github 个人博客,欢迎大佬们光临寒舍: 我的 GIthub 博客 学习导图 一.为什么要学习字节码执行引擎? 代码编译的结果从本地机器码转变为字节码,是存储格式发展的一 ...
- 深入理解JVM—字节码执行引擎
原文地址:http://yhjhappy234.blog.163.com/blog/static/3163283220122204355694/ 前面我们不止一次的提到,Java是一种跨平台的语言,为 ...
- JVM字节码执行引擎和动态绑定原理
1.执行引擎 所有Java虚拟机的执行引擎都是一致的: 输入的是字节码文件,处理过程就是解析过程,最后输出执行结果. 在整个过程不同的数据在不同的结构中进行处理. 2.栈帧 jvm进行方法调用和方法执 ...
- JVM字节码执行引擎
一.概述 在不同的虚拟机实现里面,执行引擎在执行Java代码的时候可能会有解释执行(通过解释器执行)和编译器执行(通过即时编译器产生本地代码执行)两种选择,所有的Java虚拟机的执行引擎都是一致的:输 ...
- 图解JVM字节码执行引擎之栈帧结构
一.执行引擎 “虚拟机”的概念是相对于“物理机”而言的,这两种“机器”都有执行代码的能力.物理机的执行引擎是直接建立在硬件处理器.物理寄存器.指令集和操作系统层面的:而“虚拟机”的执行引擎是 ...
- JVM学习笔记:字节码执行引擎
JVM学习笔记:字节码执行引擎 移步大神贴:http://rednaxelafx.iteye.com/blog/492667
- 深入理解JVM虚拟机5:虚拟机字节码执行引擎
虚拟机字节码执行引擎 转自https://juejin.im/post/5abc97ff518825556a727e66 所谓的「虚拟机字节码执行引擎」其实就是 JVM 根据 Class 文件中给 ...
- JVM基础结构与字节码执行引擎
JVM基础结构 JVM内部结构如下:栈.堆. 栈 JVM中的栈主要是指线程里面的栈,里面有方法栈.native方法栈.PC寄存器等等:每个方法栈是由栈帧组成的:每个栈帧是由局部变量表.操作数栈等组成. ...
- 深入理解java虚拟机(5)---字节码执行引擎
字节码是什么东西? 以下是百度的解释: 字节码(Byte-code)是一种包含执行程序.由一序列 op 代码/数据对组成的二进制文件.字节码是一种中间码,它比机器码更抽象. 它经常被看作是包含一个执行 ...
随机推荐
- 神经网络入门篇:激活函数的导数(Derivatives of activation functions)
激活函数的导数 在神经网络中使用反向传播的时候,真的需要计算激活函数的斜率或者导数.针对以下四种激活,求其导数如下: 1)sigmoid activation function 图1.8.1 其具体的 ...
- Serverless 架构就不要服务器了?
摘要:Serverless 架构不是不要服务器了,而是依托第三方云服务平台,服务端逻辑运行在无状态的计算容器中,其业务层面的状态则被开发者使用的数据库和存储资源所记录. Serverless 是什么 ...
- Shell:Lite OS在线调试工具知多少
摘要:Shell作为Huawei Liteos在线调试工具,可以通过串口工具输入输出,支持常用的基本调试功能.同时用户可以新增定制的命令,新增命令需重新编译烧录后才能执行 本文分享自华为云社区< ...
- PPT 商务图表的应用和美化之道
PPT 商务图表的应用和美化之道 折线图 饼图 你认为的图表元素,可能是图表外的元素 https://www.bilibili.com/video/BV1ha411g7f5/?p=11
- API 设计最佳实践(简版)
Restful API 本文简称API,是一个种面向资源的架构.在Restful中一个API对应一个资源,资源可以是文本,图片,视频等.API特征有如下: 每一个URI代表一种资源 客户端和服务器之间 ...
- OpenvSwitch系列之九 Group表
Open vSwitch系列之一 Open vSwitch诞生 Open vSwitch系列之二 安装指定版本ovs Open vSwitch系列之三 ovs-vsctl命令使用 Open vSwit ...
- 通义千问,阿里版ChatGPT,拿到邀请码了
大家好,我是章北海mlpy 通义千问是阿里巴巴推出的一个大型预训练模型,是达摩院自主研发的超大规模语言模型,能够回答问题.创作文字,还能表达观点.撰写代码. 昨天中午,阿里云通过官方微信公众号对旗下的 ...
- protobuf安装、编译和使用
protobuf使用简单示例 一.安装 首先下载protobuf的安装包,我这里使用的是protobuf-cpp-3.21.5.tar.gz 解压安装包 tar -xzf protobuf-cpp-3 ...
- Python | PyQt5 Could not find the Qt platform plugin windows错误解决方法
在写Python大作业的时候发现运行PyQt5时有报错 出现该问题的原因是环境变量没有添加. 解决方法: 在环境变量中增加: QT_QPA_PLATFORM_PLUGIN_PATH 样例路径(这里填你 ...
- Java解析上传的zip文件--包含Excel解析与图片上传
Java解析上传的zip文件--包含Excel解析与图片上传 前言:今天遇到一个需求:上传一个zip格式的压缩文件,该zip中包含人员信息的excel以及excel中每行对应的人的图片,现在需要将该z ...