第一句子大全,网罗天下好句子,好文章尽在本站!

一文搞懂 JVM 字节码执行引擎

时间:2012-05-04

二 核心知识点归纳2 1 概述Q1:虚拟机与物理机的异同相同点:都有代码执行能力不同点:1 物理机的执行引擎是直接建立在处理器、硬件、指令集和操作系统

友情提示:本文共有 3099 个字,阅读大概需要 7 分钟。

学习导图

一.为什么要学习字节码执行引擎?

代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,却是编程语言发展的一大步

首先,抛出灵魂三问:

虚拟机在执行代码的时候,如何找到正确的方法呢?如何执行方法内的字节码呢?执行代码时涉及的内存结构有哪些呢?如果你对上述问题理解得还不是特别透彻的话,可以看下这篇文章;如果理解了,你可以关闭网页,打开游戏放松了hhh

下面,笔者将带你探究 JVM 核心的组成部分之一——执行引擎。

二.核心知识点归纳

2.1 概述

Q1:虚拟机与物理机的异同

相同点:都有代码执行能力不同点:1.物理机的执行引擎是直接建立在处理器、硬件、指令集和操作系统层面上的2.虚拟机的执行引擎是由自定义的,可自行制定指令集与执行引擎的结构体系,且能够执行不被硬件直接支持的指令集格式

Q2:有关 JVM字节码执行引擎的概念模型

外观上:所有 JVM 的执行引擎都是一致的。输入的是字节码文件,处理的是字节码解析的等效过程,输出的是执行结果

从实现上,执行引擎有多种执行 Java 代码的选择1.解释执行:通过解释器执行2.编译执行:通过即时编译器产生本地代码执行3.两者兼备,甚至还会包含几个不同级别的编译器执行引擎

2.2 运行时栈帧结构

2.2.1 基本概念

笔者之前在 一文洞悉 JVM 内存管理机制 中就谈到过虚拟机栈,相信看过的读者都有印象

栈帧:用于支持虚拟机进行方法调用和方法执行的数据结构,是虚拟机栈的栈元素存储内容:方法的局部变量表、操作数栈、动态连接、方法返回地址和一些额外的附加信息每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程一个栈帧需要分配多少内存在程序编译期就已确定,而不会受到程序运行期变量数据的影响对于执行引擎来说,只有位于栈顶的栈帧(当前栈帧)才是有效的,即所有字节码指令只对当前栈帧进行操作,与当前栈帧相关联的方法称为当前方法

2.2.2 局部变量表

定义:局部变量表是一组变量值存储空间作用:存放方法参数和方法内部定义的局部变量分配时期:Java 程序编译为 Class 文件时,会在方法的 Code 属性的 max_locals 数据项中确定了该方法所需要分配的局部变量表的最大容量最小单位:变量槽大小:虚拟机规范中没有明确指明一个变量槽占用的内存空间大小,允许变量槽长度随着处理器、操作系统或虚拟机的不同而发生变化1. 对于 32位以内的数据类型(boolean、byte、char、short、int、float、reference、returnAddress ),虚拟机会为其分配一个变量槽空间2. 对于 64位的数据类型(long、double),虚拟机会以高位对齐的方式为其分配两个连续的变量槽空间3. 特点:可重用。为了尽可能节省栈帧空间,若当前字节码PC 计数器的值已超出了某个变量的作用域,则该变量对应的变量槽可交给其他变量使用

访问方式:通过索引定位。索引值的范围是从 0 开始至局部变量表最大的变量槽数量局部变量表第一项是名为 this 的一个当前类引用,它指向堆中当前对象的引用(由反编译得到的局部变量表可知)

2.2.3 操作数栈

操作数栈是一个后入先出栈作用:在方法执行过程中,写入(进栈)和提取(出栈)各种字节码指令分配时期:同上,在编译时会在方法的 Code 属性的 max_stacks 数据项中确定操作数栈的最大深度栈容量:操作数栈的每一个元素可以是任意的 Java 数据类型 ——32 位数据类型所占的栈容量为 1,64 位数据类型所占的栈容量为 2注意:操作数栈中元素的数据类型必须与字节码指令的序列严格匹配,在编译时编译器需要验证一次、在类校验阶段的数据流分析中还要再次验证2.2.4 动态连接

定义:每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接静态解析和动态连接区别:Class 文件的常量池中存有大量的符号引用,字节码中的方法调用指令就以常量池中指向方法的符号引用作为参数,这些符号引用:1. 一部分会在类加载阶段或者第一次使用的时候就转化为直接引用(静态解析)2. 另一部分会在每一次运行期间转化为直接引用(动态连接)

2.2.5 方法返回地址

方法退出的两种方式:

1. 正常退出:执行中遇到任意一个方法返回的字节码指令2. 异常退出:执行中遇到异常、且在本方法的异常表中没有搜索到匹配的异常处理器区处理

作用:在方法返回时都可能在栈帧中保存一些信息,用于恢复上层方法调用者的执行状态1. 正常退出时,调用者的 PC 计数器的值可以作为返回地址2. 异常退出时,通过异常处理器表来确定返回地址

方法退出的执行操作:1. 恢复上层方法的局部变量表和操作数栈2. 若有返回值把它压入调用者栈帧的操作数栈中3. 调整 PC 计数器的值以指向方法调用指令后面的一条指令等

在实际开发中,一般会把动态连接、方法返回地址与其他附加信息全部一起称为栈帧信息

2.3 方法调用

方法调用是最普遍且频繁的操作任务:确定被调用方法的版本,即调用哪一个方法,不涉及方法内部的具体运行过程下面笔者将为大家详细讲解方法调用的类型

2.3.1 解析调用

笔者之前在 一夜搞懂 | JVM 类加载机制中就谈到过解析,感觉有点混淆的,可以回去看下

特点:是静态过程在编译期间就完全确定,在类装载的解析阶段就会把涉及的符号引用全部转变为可确定的直接引用,而不会延迟到运行期再去完成,即编译期可知、运行期不变适用对象:private 修饰的私有方法,类静态方法,类实例构造器,父类方法2.3.2 分派调用

Q1:什么是静态类型?什么是实际类型?

A1:这个用代码来说比较简便, Talk is cheap ! Show me the code !

1.静态分派

1. 依赖静态类型来定位方法的执行版本2. 典型应用是方法重载3. 发生在编译阶段,不由 JVM 来执行单纯说未免有些许抽象,所以特地用下面的 DEMO 来帮助了解

输出结果如下:

hello , i am the fatherhello , i am the father

我们的编译器在生成字节码指令的时候会根据变量的静态类型选择调用合适的方法。就我们上述的例子而言:

2.动态分派

1. 依赖动态类型来定位方法的执行版本2. 典型应用是方法重写3. 发生在运行阶段,由 JVM 来执行单纯说未免有些许抽象,所以特地用下面的 DEMO 来帮助了解

输出结果如下:

hello world ---- son

我们接着来看一下字节码指令调用情况

疑惑来了,我们可以看到,JVM 选择调用的是静态类型的对应方法,但是为什么最终的结果却调用了是实际类型的对应方法呢?

当我们将要调用某个类型实例的具体方法时,会首先将当前实例压入操作数栈,然后我们的 invokevirtual 指令需要完成以下几个步骤才能实现对一个方法的调用:

因此,疑惑自然解决了

3.单分派

含义:根据一个宗量对目标方法进行选择(方法的接受者与方法的参数统称为方法的宗量)

4.多分派

含义:根据多于一个宗量对目标方法进行选择

想了解 静态多分派,动态单分派的可以看下这篇文章:Java 中的静态单多分派与动态单分派

三.碎碎念

恭喜你!已经看完了前面的文章,相信你对JVM字节码执行引擎已经有一定深度的了解!你可以稍微放松奖励自己一下,可以睡一个美美的觉,明天起来继续冲冲冲!

如果文章对您有一点帮助的话,希望您能点一下赞,您的点赞,是我前进的动力

想了解更多精彩内容,快来关注计算机java编程

本文如果对你有帮助,请点赞收藏《一文搞懂 JVM 字节码执行引擎》,同时在此感谢原作者。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。
相关阅读
大牛巧用一文带你彻底搞懂解释器的内部构造和解释执行过程

大牛巧用一文带你彻底搞懂解释器的内部构造和解释执行过程

模板解释器最简单的Java虚拟机可以只包括类加载器和解释器:类加载器加载字节码iconst_1、iconst_1、iadd并传给虚拟机,解释器按照字节码计算并得到结果。在没有JIT编译器的情况下,解释器从某种程度上来说就是虚拟机本体,有...

2008-09-27 #经典句子

JDK成长记14:(深度好文)从3个层面分析volatile底层原理(下)

JDK成长记14:(深度好文)从3个层面分析volatile底层原理(下)

...是通过类加载器加载class到JVM内存区域,之后又通过执行引擎来执行JVM指令。不同的过JDK版本有不同的的JVM实现。有耳熟能详的HotSpot,有淘宝自己的JVM实现,还有J9、OpenJDK等其他的JVM实现……但JDK1.8后,最常见的就是HotSpot的JVM的...

2014-01-26 #经典句子

浅析 Java 程序语言的运行机制

浅析 Java 程序语言的运行机制

...再进行解释两个步骤。解释型和编译型计算机按照程序的执行方式可以分为解释型和编译型。解释型语言(Interpreted language)这种类型的编程语言,会将代码一句一句直接运行,不需要像编译语言(Compiled language)一样,经过编...

2009-06-06 #经典句子

Java语言编程基础100题期末复习

Java语言编程基础100题期末复习

...个方法才能运行?A.Start() B.Begin() C.Method() D.Main()4. 执行编译好的Java程序的命令是A.javac B.java 5. 可以将以下哪个值赋给类型char的变量?(1)’A’ (2)9 (3)12.3 (4)”hello”A.(1)和(2) B.(1).(2)和(3) C.(1) D.(2)6. Jav...

2024-01-15 #经典句子

万字长文 一篇吃透WebSocket:概念 原理 易错常识 动手实践

万字长文 一篇吃透WebSocket:概念 原理 易错常识 动手实践

...IM通信技术快速入门:短轮询、长轮询、SSE、WebSocket》《搞懂现代Web端即时通讯技术一文就够:WebSocket、socket.io、SSE》6、WebSocket学习过程中的易错常识6.1 WebSocket 与 HTTP 有什么关系?WebSocket 是一种与 HTTP 不同的协议。两者都位于...

2023-12-31 #经典句子

@程序员 快来速取硬核的汇编语言知识大全!

@程序员 快来速取硬核的汇编语言知识大全!

...要经过编译器编译后,转换为本地代码才能够被 CPU 解释执行。但是本地代码的可读性非常差,所以需要使用一种能够直接读懂的语言来替换本地代码,那就是在各本地代码中,附带上表示其功能的英文缩写,比如在加法运算的...

2023-01-23 #经典句子

学员问:C语言入门要掌握哪些基础知识?

学员问:C语言入门要掌握哪些基础知识?

...含这个结构。括号内可以不写任何内容,那么该程序将不执行任何结果。2、main()——在c语言中称之为“主函数”,一个c程序有且仅有一个main函数,任何一个c程序总是从main函数开始执行,main函数后面的一对圆括号不能省略。3...

2010-02-07 #经典句子

“WebAssembly 将会取代 Docker” 但还有后半句

“WebAssembly 将会取代 Docker” 但还有后半句

...的地方。所以,WebAssembly 有很大前景变成一个通用的计算执行环境或者容器,不仅会放在云端,也会用在边缘设备上。成为服务网格里的“一等公民”OSCHINA:WasmEdge 0.8.2全新版本有哪些功能更新?跨平台能力提升、增加了golang sd...

2023-09-07 #经典句子