字节码解释执行引擎

wade&luffy wade&luffy     2022-08-13     275

关键词:

虚拟机是如何执行方法中的字节码指令的。许多Java虚拟机的执行引擎在执行Java代码的时候都有解释执行(通过解释器执行)和编译执行(通过即时编译器产生本地代码执行)两种选择,在解释执行时,虚拟机执行引擎是如何工作的。

解释执行

不论是解释还是编译,也不论是物理机还是虚拟机,对于应用程序,机器都不可能如人那样阅读、理解,然后就获得了执行能力。大部分的程序代码到物理机的目标代码或虚拟机能执行的指令集之前,都需要经过图中的各个步骤。很容易就会发现图中下面那条分支,就是传统编译原理中程序代码到目标机器代码的生成过程,而中间的那条分支,自然就是解释执行的过程。如今,基于物理机、Java虚拟机,或者非Java的其他高级语言虚拟机(HLLVM)的语言,大多都会遵循这种基于现代经典编译原理的思路,在执行前先对程序源码进行词法分析和语法分析处理,把源码转化为抽象语法树(Abstract Syntax Tree,AST)。对于一门具体语言的实现来说,词法分析、语法分析以至后面的优化器和目标代码生成器都可以选择独立于执行引擎,形成一个完整意义的编译器去实现,这类代表是C/C++语言。也可以选择把其中一部分步骤(如生成抽象语法树之前的步骤)实现为一个半独立的编译器,这类代表是Java语言。又或者把这些步骤和执行引擎全部集中封装在一个封闭的黑匣子之中,如大多数的JavaScript执行器。

基于栈的指令集与基于寄存器的指令集

Java编译器输出的指令流,基本上(使用“基本上”,是因为部分字节码指令会带有参数,而纯粹基于栈的指令集架构中应当全部都是零地址指令,也就是都不存在显式的参数。Java这样实现主要是考虑了代码的可校验性)是一种基于栈的指令集架构(Instruction Set Architecture,ISA),指令流中的指令大部分都是零地址指令,它们依赖操作数栈进行工作。与之相对的另外一套常用的指令集架构是基于寄存器的指令集,最典型的就是x86的二地址指令集,说得通俗一些,就是现在我们主流PC机中直接支持的指令集架构,这些指令依赖寄存器进行工作。那么,基于栈的指令集与基于寄存器的指令集这两者之间有什么不同呢?

举个最简单的例子,分别使用这两种指令集计算“1+1”的结果,基于栈的指令集会是这样子的:

iconst_1

iconst_1

iadd

istore_0

两条iconst_1指令连续把两个常量1压入栈后,iadd指令把栈顶的两个值出栈、相加,然后把结果放回栈顶,最后istore_0把栈顶的值放到局部变量表的第0个Slot中。

如果基于寄存器,那程序可能会是这个样子:

mov eax,1

add eax,1

mov指令把EAX寄存器的值设为1,然后add指令再把这个值加1,结果就保存在EAX寄存器里面。

了解了基于栈的指令集与基于寄存器的指令集的区别后,这两套指令集谁更好一些呢?

应该这么说,既然两套指令集会同时并存和发展,那肯定是各有优势的,如果有一套指令集全面优于另外一套的话,就不会存在选择的问题了。

基于栈的指令集主要的优点就是可移植,寄存器由硬件直接提供,程序直接依赖这些硬件寄存器则不可避免地要受到硬件的约束。例如,现在32位80x86体系的处理器中提供了8个32位的寄存器,而ARM体系的CPU(在当前的手机、PDA中相当流行的一种处理器)则提供了16个32位的通用寄存器。如果使用栈架构的指令集,用户程序不会直接使用这些寄存器,就可以由虚拟机实现来自行决定把一些访问最频繁的数据(程序计数器、栈顶缓存等)放到寄存器中以获取尽量好的性能,这样实现起来也更加简单一些。栈架构的指令集还有一些其他的优点,如代码相对更加紧凑(字节码中每个字节就对应一条指令,而多地址指令集中还需要存放参数)、编译器实现更加简单(不需要考虑空间分配的问题,所需空间都在栈上操作)等。栈架构指令集的主要缺点是执行速度相对来说会稍慢一些。所有主流物理机的指令集都是寄存器架构也从侧面印证了这一点。虽然栈架构指令集的代码非常紧凑,但是完成相同功能所需的指令数量一般会比寄存器架构多,因为出栈、入栈操作本身就产生了相当多的指令数量。更重要的是,栈实现在内存之中,频繁的栈访问也就意味着频繁的内存访问,相对于处理器来说,内存始终是执行速度的瓶颈。尽管虚拟机可以采取栈顶缓存的手段,把最常用的操作映射到寄存器中避免直接内存访问,但这也只能是优化措施而不是解决本质问题的方法。由于指令数量和内存访问的原因,所以导致了栈架构指令集的执行速度会相对较慢。

基于栈的解释器执行过程

看看在虚拟机中实际是如何执行的。

public int calc(){
    int a=100int b=200int c=300return(a+b)*c;
}

从Java语言的角度来看,这段代码没有任何解释的必要,可以直接使用javap命令看看它的字节码指令

public int calc();
Code:
Stack=2,Locals=4,Args_size=1
0:bipush 100
2:istore_1
3:sipush 200
6:istore_2
7:sipush 300
10:istore_3
11:iload_1
12:iload_2
13:iadd
14:iload_3
15:imul
16:ireturn

javap提示这段代码需要深度为2的操作数栈和4个Slot的局部变量空间。

上面的执行过程仅仅是一种概念模型,虚拟机最终会对执行过程做一些优化来提高性能,实际的运作过程不一定完全符合概念模型的描述……更准确地说,实际情况会和上面描述的概念模型差距非常大,这种差距产生的原因是虚拟机中解析器和即时编译器都会对输入的字节码进行优化,例如,在HotSpot虚拟机中,有很多以“fast_”开头的非标准字节码指令用于合并、替换输入的字节码以提升解释执行性能,而即时编译器的优化手段更加花样繁多。

 

虚拟机字节码执行引擎

...作数栈、动态链接、方法返回地址。执行引擎运行的所有字节码指令都只针对虚拟机栈顶的栈帧而言。局部变量表  局部变量表(Local Variable Table)是一组变量值存储空间,用于存放方法参数、方法内部定义的局部变量... 查看详情

java虚拟机-字节码执行引擎

概述Java虚拟机规范中制定了虚拟机字节码执行引擎的概念模型,成为各种虚拟机执行引擎的统一外观(Facade)。不同的虚拟机引擎会包含两种执行模式,解释执行和编译执行。运行时帧栈结构栈帧(StackFrame)支持虚拟机进行方... 查看详情

--字节码执行引擎

执行引擎概述执行引擎属于JVM的下层,里面包括:解释器、及时编译器、垃圾回收器执行引擎是Java虚拟机核心的组成部分之一。“虚拟机”是一个相对于“物理机”的概念,这两种机器都有代码执行能力,其区别... 查看详情

jvm--12---执行引擎----解释器jit编译器

...va代码编译和执行过程Java代码编译Java源代码==>JVM字节码Java字节码的执行JVM字节码==>执行解释器(In 查看详情

深入理解jvm学习笔记——-8虚拟机字节码执行引擎(代码片段)

八、虚拟机字节码执行引擎你只管努力,——剩下的交给时光。老规矩,先上图,大致了解一下:一.概述执行引擎是Java虚拟机最核心的组成部分之一。“虚拟机”是一个相对于“物理机”的概念,这两种机器... 查看详情

基于栈的虚拟机字节码执行引擎

一、虚拟机字节码执行引擎概述  虚拟机字节码执行引擎主要就是研究字节码指令具体怎样被执行。对于物理机器,指令的执行是直接建立在OS和硬件的基础上对于字节码指令的执行就是直接建立在JVM上,然后通过JVM完成具体... 查看详情

jvm详解——执行引擎

...被硬件直接支持的指令集格式。JVM的主要任务是负责装载字节码到其内部,但字节码并不能够直接运行在操作系统之上,因为字节码指令并非等价于本地机器指令,它内部包含的仅仅只是一些能够被JVM所识别的字节码... 查看详情

java的核心技术啥?

...拟机Java虚拟机的主要任务是装在class文件并且执行其中的字节码。Java虚拟机包含一个类装载器,它可以从程序和API中装载class文件。JavaAPI中只有程序执行时需要的那些类才会被装载。字节码由执行引擎来执行。不同的Java虚拟机... 查看详情

虚拟机字节码执行引擎

前言  代码编译的结果从本地机器转变为字节码,是存储格式发展的一小步,却是编程语言发展的一大步。概述  执行引擎是Java虚拟机最核心的组成部分之一。虚拟机是一个相对于物理机的概念,这两种机器都有代码执行... 查看详情

java的核心技术都有哪些?

... Java虚拟机的主要任务是装在class文件并且执行其中的字节码。Java虚拟机包含一个类装载器,它可以从程序和API中装载class文件。JavaAPI中只有程序执行时需要的那些类才会被装载。字节码由执行引擎来执行。不同的Java虚拟机... 查看详情

java的四个核心思想

...拟机Java虚拟机的主要任务是装在class文件并且执行其中的字节码。Java虚拟机包含一个类装载器,它可以从程序和API中装载class文件。JavaAPI中只有程序执行时需要的那些类才会被装载。字节码由执行引擎来执行。  不同的Java虚... 查看详情

一夜搞懂|jvm字节码执行引擎

...佬们光临寒舍:我的GIthub博客学习导图一.为什么要学习字节码执行引擎?代码编译的结果从本地机器码转变为字节码,是存储格式发展的一小步,却是编程语言发展的一大步首先,抛出灵魂三问:虚拟机在执行代码的时候,如... 查看详情

字节码执行方式--解释执行和jit

...品运营经验。1、两种执行方式:解释执行(运行期解释字节码并执行)强制使用该模式:-Xint编译为机器码执行(将字节码编译为机器码并执行,这个编译过程发生在运行期,称为JIT编译)强制使用该模式:-Xcomp,下面是两种编... 查看详情

字节码执行方式--解释执行和jit

...品运营经验。1、两种执行方式:解释执行(运行期解释字节码并执行)强制使用该模式:-Xint编译为机器码执行(将字节码编译为机器码并执行,这个编译过程发生在运行期,称为JIT编译)强制使用该模式:-Xcomp,下面是两种编... 查看详情

虚拟机字节码执行引擎(代码片段)

字节码就像是汇编语言,是JVM的指令集。执行引擎是Java虚拟机最核心的组成部分之一。“虚拟机”是一个相对于“物理机”的概念,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器、... 查看详情

jvm字节码执行引擎和动态绑定原理

...行引擎所有Java虚拟机的执行引擎都是一致的:输入的是字节码文件,处理过程就是解析过程,最后输出执行结果。在整个过程不同的数据在不同的结构中进行处理。2.栈帧jvm进行方法调用和方法执行的数据结构,是虚拟机栈的元... 查看详情

java源代码怎么执行的

...为:编写java文件源码通过javac编译器将java源码编译为字节码流通过解释器解释执行字节码随着时间推移,即时编译器(JIT)介入,把越来越多的字节码编译 查看详情

深入理解java虚拟机06--虚拟机字节码执行引擎

...拟机规范),不同类型的虚拟机都遵循了这一规范,输入字节码文件,解析字节码处理,然后输出结果。二.运行时栈帧结构1、栈帧概念栈帧(StackFrame)用于支持方法调用和执行的数据结构,包含了局部变量表、操作数栈、动态... 查看详情