1.执行引擎概述
执行引擎:虚拟机的执行引擎则是由软件自行实现的,无需物理条件制约的指令集与体系结构;能执行不被硬件支持的指令集格式。
JVM的主要任务是负责装载字节码到其内部,但字节码并不能直接运行在OS上,因为字节码指令并非等价本地机器指令,它内部包含的仅仅只是一些能被JVM所识别的字节码指令、符号表,及其他辅助信息。
若想JAVA程序运行,执行引擎的任务就是将字节码指令解释/编译为对应平台上的本地机器指令才可以。即执行引擎充当了高级语言翻译为机器语言的翻译者。
1.1.执行引擎的工作过程
1.执行引擎在执行的过程中究竟需要执行什么样的字节码指令完全依赖于PC寄存器;
2.每当执行完一项指令操作后,PC寄存器就会更新下一条需要被执行的指令地址。
3.当然方法在执行的过程中,执行引擎有可能会通过存储在局部变量表中的对象引用准确定位到存储在JAVA堆区中的对象实例信息,以及通过对象头中的元数据指针定位到目标对象的类型信息。
Java代码编译和执行的过程
大部分的程序代码转换成物理机的目标代码或虚拟机能执行的指令集之前,都需要经过上图各个步骤。
如图1的橙色部分对应下图:
JAVAC把代码编译成.class文件过程;JAVA代码编译是有JAVA源码编译器来完成的:
如图1的绿色和蓝色部分:
JAVA字节码的执行是由JVM执行引擎来完成:
解释器Interpreter
对应图1的绿色部分;当JVM启动时会根据预定义的规范对字节码采用逐行解释的方式执行,将每条字节码文件中的内容翻译为对应平台的本地机器指令执行。
编译器JIT(后端编译器)
对应图1的蓝色部分;JVM将源代码直接编译成和本地机器平台相关的机器语言。
方法区会缓存JIT编译的结果;
Java是半编译型,半解释型语言
JVM执行JAVA代码的时候,同时会将解释执行与编译执行二者结合起来进行。
3.机器码、指令和汇编语言
机器码:
指令:
汇编语言
高级语言
计算机编译
c、c++程序执行过程
字节码
4.解释器
JVM设计者初衷仅仅只是单纯为满足Java程序实现跨平台特性,因此避免采用静态编译的方式直接生成本地机器指令,从而诞生了实现解释器在运行时采用逐行解释字节码执行程序。
4.1解释器工作原理
4.2解释器分类
字节码解释器、模板解释器
4.3 解释器现状
5.JIT编译器
5.1JAVA代码的执行分类
一种解释器解释字节码为机器码执行;
一种编译执行,将字节码转换成机器码;
5.2 HotSpot采用解释器与即时编译器并存
5.3 解释器与即时编译比较
1.解释器马上响应,延时少,但执行慢;
2.JIT编译慢,有延时,但执行快;
JRockit是没有解释器的,因为它针对服务器端开发;对响应要求低;
5.4 HotSpot JVM的执行方式
启动时解释器发挥作用,延时少;省去编译时间;
运行过程中,JIT编译好代码后,再执行则快很多;
5.5 JIT编译器
前端编译器:增量式编译器(ECJ)
JIT编译器:Hotspot JVM中的C1、C2编译器;
AOT编译器:GCJ、JET
5.6 编译器选择
热点代码:执行频率比较高的代码;
热点代码探测
栈上替换(OSR):被多次调用的方法,一个方法中循环次数较多的循环体(热点代码),直接可通过JIT编程器编译为本地机器指令;
计数器:计数器会记录方法调用多少次;调用次数多的直接进行OSR;
1.方法调用计数器
JIT代码编译后一定要缓存Code Cach;在方法区中(本地内存的元空间中);
热度衰减
当超过一定时间限度,若方法的调用次数仍然不足让它提交给JIT,方法的调用计数器就会被减少一半。
2.回边计数器
循环体执行的次数
5.7 Hotspot VM设置程序执行方式
5.8 HotSpot JIT分类
1.client(C1编译器)模式
2.server(C2编译器)模式:64位操作系统,默认就是server模式,无法修改;
5.8.1 C1和C2编译器不同的优化策略
5.9 总结
一般,JIT编译出来的机器码性能比解释器高;
C2编译器启动时长比C1编译器慢,系统稳定执行以后,C2编译器执行速度远远快于C1编译器。
5.10 JIT的Graal发展
5.11 AOT编译器(与JIT对应)
JIT是在程序运行中编译;将字节码转换为可在硬件上直接运行的机器码;
AOT是在程序运行前编译;将字节码转换为可在硬件上直接运行的机器码;
AOT的优点与缺点