深入理解java:1.2. 字节码执行引擎

摘要:
执行引擎是Java虚拟机的核心组件之一。执行引擎执行过程:输入是内存中的字节码,处理是字节码解析的等效过程,输出是执行结果。然而,虚拟机的出现是为了提供跨平台支持,因此jvm的执行引擎是一个基于堆栈的指令集。当继续执行方法时,JVM主要提供invokestatic、invokevirtual、invoikeinterface和invokespecial指令来执行。如果该方法不再频繁使用,则编译后的代码将被取消,并仍然被解释和执行;芯片级直接执行:嵌入在芯片上,使用本地方法执行Java字节码。

执行引擎是Java虚拟机的核心组成部分之一。

首先,想想C++和Java在编译和运行时到底有啥不一样?

下图左边,C++发布的就是机器指令,

而下图右边Java发布的是字节码,字节码在运行时通过JVM的类加载器,加载到JVM的虚拟内存的方法区,

再通过编译器、解释器做一次转换生成机器指令。执行引擎正是执行了这样的过程:输入的是内存中的字节码,处理过程是字节码解析的 等效过程,输出的是执行结果。

深入理解java:1.2. 字节码执行引擎第1张

其次,再来看下图,JVM的内存结构:

深入理解java:1.2. 字节码执行引擎第2张

一、执行方法。

每个线程在创建后,都会产生一个程序计数器(pc)和栈(Stack)。

其中pc中存放了下一条将要执行的指令;

Stack中存放Stack Frame,存储了 当前正在执行的方法的信息,

每个方法的执行都会产生Stack Frame,Stack Frame中存放了   传递给方法的参数、方法内的局部变量以及操作数栈;

操作数栈用于存放指令运算的中间结果;

操作数栈在概念上很像CPU寄存器(CPU的内部元件:指令寄存器IR和程序计数器PC)。

java虚拟机无法使用寄存器,所以就用 操作数栈 来存放数据。

虚拟机把操作数栈作为它的工作区 —— 大多数指令都要从这里弹出数据,执行运算,然后把结果压回操作数栈。

比如,iadd指令就要从操作数栈中弹出两个整数,执行加法运算,其结果又压回到操作数栈中。

基于(操作数)栈的指令集 和基于寄存器的区别,

基于栈的指令集 是和硬件无关的,而基于寄存器则依赖于硬件基础。

基于寄存器在效率上优势。

但是虚拟机的出现,就是为了提供跨平台的支持,所以jvm的执行引擎是基于栈的指令集。

当方法执行完毕后则从Stack中弹出,继续其他方法的执行。

在继续执行方法时,JVM主要提供了invokestatic、invokevirtual、invokeinterface和invokespecial四种指令来执行。

在类加载的第二阶段--链接的第三阶段--解析,就确定下来的,属于编译期可知,运行期不可变的方法:

(1) invokestatic:调用类的static方法,属于绑定类的调用

(2) invokespecial: 调用构造器,私有方法和父类方法,外部不可访问,绑定实例对象

还有一种是在运行时候解析的,只有在运行时才能确定下来的,主要包含以下两方面:

(3) invokeinterface:调用接口方法,不确定调用那一个实现类

(4) invokevirtual: 调用虚方法,不确定调用哪一个实现类 

二、执行技术

主要的执行技术有:解释,即时编译,自适应优化、芯片级直接执行

(1)解释:属于第一代JVM;

(2)即时编译:JIT属于第二代JVM;

(3)自适应优化:(目前Sun的HotspotJVM采用这种技术)吸取第一代JVM和第二代JVM的经验,采用两者结合的方式。

开始对所有的代码都采取解释执行的方式,

并监视代码执行情况,然后对那些 经常 调用的方法启动一个后台线程,将其编译为本地代码,并进行仔细优化。

若方法不再频繁使用,则取消编译过的代码,仍对其进行解释执行;

(4)芯片级直接执行:内嵌在芯片上,用本地方法执行Java字节码。

免责声明:文章转载自《深入理解java:1.2. 字节码执行引擎》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇关于枚举的种种03生成微博授权的url接口(再也没有你了)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

ARM寻址方式

立即数寻址: 操作数本身就在指令中 例子:ADD R0,R0,#0X3F(注意:立即数需要在数据前面加上一个#号) 寄存器寻址: 利用寄存器中的数值作为操作数,数据存在寄存器中 例子:ADD R0,R1,R2 寄存器间接寻址: 数据存放在内存中,寄存其中存放的不是操作数本身,而是其在内存中的地址。通常需要加上一个[] 例子:LDR R0,[R2] 基地址变...

C++ 术语(C++ Primer)

argument(实参):传递给被调用函数的值。block(块):花括号括起来的语句序列。buffer(缓冲区):一段用来存放数据的存储区域。IO 设备常存储输入(或输出)到缓冲区,并独立于程序动作对缓冲区进行读写。输出缓冲区通常必须显式刷新以强制输出缓冲区内容。默认情况下,读 cin 会刷新 cout;当程序正常结束时,cout 也被刷新。built-i...

Intel 8086 常用汇编指令表

一、数据传输指令   它们在存贮器和寄存器、寄存器和输入输出端口之间传送数据.   1. 通用数据传送指令.     MOV  传送字或字节.     MOVSX 先符号扩展,再传送.     MOVZX 先零扩展,再传送.     PUSH  把字压入堆栈.     POP  把字弹出堆栈.     PUSHA 把AX,CX,DX,BX,SP,BP,SI...

Python基础:第一个Python程序(2)

1.Python Shell 1.1 Windows命令 (1)【开始】|【运行】,输入cmd回车,进入Windows命令界面。 (2)输入python,回车,进入Python Shell。 1.2 IDLE Python开始菜单中点击IDLE,启动Python Shell。 2.Python文件 2.1 py源码文件 hello_world.py:...

字节码指令简介(转)

字节码指令简介(转) 原文阅读 操作码:一个字节长度、代表某种特定操作含义的数字。 操作数:跟在操作码后面0个或多个代表此操作所需的参数。 Java虚拟机的指令 = 操作码 + 操作数。由于Java虚拟机采用面向操作数栈,所以大多指令都不包含操作数,只有一个操作码。 Java虚拟机的解释器(不考虑异常): do { 自动计算PC寄存器...

jvm之java类加载机制和类加载器(ClassLoader),方法区结构,堆中实例对象结构的详解

一.类加载或类初始化:当程序主动使用某个类时,如果该类还未被加载到内存中,则JVM会通过加载、连接、初始化3个步骤来对该类进行初始化。如果没有意外,JVM将会连续完成3个步骤。 二.类加载时机: 1.创建类的实例,也就是new一个对象 2.访问某个类或接口的静态变量,或者对该静态变量赋值 3.调用类的静态方法 4.反射(Class.forName("com...