• 虚拟机字节码操作引擎-----基于栈的字节码解释引擎


    虚拟机调用方法可以有解析和分派两种方式,那么虚拟机是如何执行方法中的字节码指令的?

    1.解释执行

     

    谈是解释执行还是翻译执行没有意义了,只有确定了某种具体的java实现版本和执行引擎运行模式时,谈解释执行还是编译执行才比较贴切。

    如今,基于物理机、java虚拟机,或者非Java的其他高级语言虚拟机的语言,大多都会遵循这种基于现代经典编译原理的思路,在执行前先对程序源码进行词法分析和语法分析处理,把源码转化为抽象语法树 。对于一门具体语言的实现来说,词法分析、语法分析以致后面的优化器和目标代码生成器都可以选择独立于执行引擎,形成一个完整意义的编译器趋势线,这类代表是C/C++语言。也可以选择把其中一部分步骤实现为一个半独立的编译期,这类代表是java语言。又或者把这些步骤和执行引擎全部集中封装在一个封闭的黑匣子之中,如大多数的JavaScript执行器。

    Java语言中,javac编译器完成了程序代码经过词法分析、语法分析到抽象语法树,再遍历语法树生成线性的字节码指令刘的过程。因为这一部分动作是在java虚拟机之外进行的,而解释器在虚拟机内部,所以java程序的编译就是半独立的实现。

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

    java编译器输出的指令刘,基本上是一种基于栈的指令集架构,指令流之中大部分都会是零地址指令,他们依赖于操作数栈进行工作。与之相对的另外一套常用的指令集架构是基于寄存器的指令集,最典型的就是x86的二进制指令集,也是我们主流PC机中直接支持的指令集架构,这些指令依赖寄存器进行工作。这两种有什么不同?

    举个例子:1+1

    基于栈的指令集会是:

    iconst_1
    iconst_1
    iadd
    istore_0

    如果基于寄存器,程序可能是:

    mov eax,1
    add eax,1

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

    优缺点:

     基于栈的指令集主要的优点就是可移植,寄存器由硬件直接提供,程序直接依赖这些硬件寄存器则不可避免地要受到硬件的约束。缺点是执行速度相对来说稍慢一点。

    ③基于栈的解释器执行过程

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

    执行偏移地址 解释 程序计数器 局部变量表 栈顶
    0 将100推送到栈顶 0 this 100
    1 将100出栈放到第一个局部变量slot中 1 this 100 null
    11 第一个局部变量slot中的数值复制到栈顶 11

    this

    100

    200

    300

    100
    12 第二个局部变量slot中的数值复制到栈顶 12

    this

    100

    200

    300

    200
    13 将200和100出栈,加完之后入栈 13

    this

    100

    200

    300

    300
    14 b把300复制到操作数栈中,imul和iadd完全类似,下面省略 14

    this

    100

    200

    300

    300
    16 结束方法并将操作舒展定的整型值返回给此方法的调用者 16

    this

    100

    200

    300

    90000
  • 相关阅读:
    ES6-Generator
    ES6-Iterator & for...of循环
    ES6-Proxy and Reflect
    在Main中定义student的结构体,进行年龄从大到小依次排序录入学生信息。(结构体的用法以及冒泡排序)
    函数的调用(取两个整型变量中的最大值)
    将一个字符串数组的元素的顺序进行翻转。。
    枚举类型练习
    利用Arraylist输入学生的成绩,求出平均分和总分。
    简单的推箱子游戏(利用数组)
    枚举类型的声明
  • 原文地址:https://www.cnblogs.com/wxw7blog/p/7278369.html
Copyright © 2020-2023  润新知