【探究JVM八】Java的核心动力——执行引擎

【探究JVM八】Java的核心动力——执行引擎

1. 执行引擎概述

Java程序能够跨平台执行的原因并不是语言本身具备的的跨平台,而是每个平台对应实现了相应的虚拟机,来保证在不同操作系统下执行的一致性。是不同操作系统下的虚拟机,保证了Java的跨平台特性

【探究JVM八】Java的核心动力——执行引擎

我们都知道,Java是半编译半解释性的语言,先将.java文件编译成.class文件,然后通过Java虚拟机来解释执行。

JM的主要任务是负责装载字节码到其内部,但字节码并不能够直接运行在操作系统之上,因为字节码指令不等价于本地机器指令,它内部包含的仅仅只是一些能够被JVM所识别的字节码指令、符号表,以及其他辅助信息。

【探究JVM八】Java的核心动力——执行引擎

那么,如果想要让一个Java程序运行起来,执行引擎( Execution Engine)的任务就是将字节码指令解释/编译为对应平台上的本地机器指令才可以。

简单来说,JVM中的执行引擎充当了将高级语言翻译为机器语言的翻译官。

2. 执行引擎工作过程

【探究JVM八】Java的核心动力——执行引擎

  1. 执行引擎要执行什么字节码指令,完全依赖于PC计数器。PC计数器存放着下一条执行指令的地址。

  2. 每当执行引擎执行完一条指令后,PC计数器会更新下一条指令的地址。执行引擎寻得后执行。

  3. 方法在执行的过程中,执行引擎有可能会通过存储在局部变量表中的对象引用,准确定位到存储在Java堆区中的对象实例信息,以及通过对象头中的元数据指针定位到目标对象的类型信息


3. 前端编译器与后端编译器

????参考文章【Java编译分类:前端编译和后端编译是如何划分的

Java程序代码需要编译后才能在虚拟机中运行,编译涉及到非常多的知识层面:编译原理、语言规范、虚拟机规范、本地机器码优化等。

下面我们先来看Java体系中的三种编译方式:前端编译、即时编译(JIT编译)、静态提前编译(AOT编译)

前端编译

把Java源码文件.java编译成Class文件.class的过程;

即把满足Java语言规范的程序转化为满足JVM规范所要求格式的功能;

优点:

这阶段的优化是指程序编码方面的;

  • 许多Java语法新特性(“语法糖”:泛型、内部类等等),是靠前端编译器实现的,而不是依赖虚拟机;

  • 编译成的Class文件可以直接给JVM解释器解释执行,省去编译时间,加快启动速度;

缺点:

  • 对代码运行效率几乎没有任何优化措施;

  • 解释执行效率较低,所以需要结合下面的JIT编译;

前端编译器:Oracle javac、Eclipse JDT中的增量式编译器(ECJ)等;

后端编译

通过Java虚拟机(JVM)内置的即时编译器(Just In Time Compiler,JIT编译器);在运行时把Class文件字节码编译成本地机器码的过程;

优点:

  • 通过在运行时收集监控信息,把"热点代码"(Hot Spot Code)编译成与本地平台相关的机器码,并进行各种层次的优化;

  • 可以大大提高执行效率;

缺点:

  • 收集监控信息影响程序运行;

  • 编译过程占用程序运行时间(如使得启动速度变慢);

  • 编译机器码占用内存;

JIT编译器:HotSpot虚拟机的C1、C2编译器等;

程序运行前,直接把Java源码文件.java编译成本地机器码的过程;

另外,JIT编译速度及编译结果的优劣,是衡量一个JVM性能的很重要指标;

所以对程序运行性能优化集中到这个阶段,也就是说可以对这个阶段进行JVM调优


4. Java程序的编译与执行

【探究JVM八】Java的核心动力——执行引擎

什么是解释器?什么是JIT编译器?

解释器( Interpreter):当Java虚拟机启动时,会根据预定义的规范对字节码采用逐行解释的方式执行,将每条字节码文件中的内容“翻译”为对应平台的本地机器指令执行

  • 解释器将.class字节码指令解释为本地机器指令

JIT( Just In Time Compiler)即时编译器:就是虚拟机将源代码直接编译成和本地机器平台相关的机器语言

  • JIT将.java代码直接编译为本地机器指令

这里所说的编译器是指后端编译器

理解Java-半编译半解释型语言

为什么Java被称作是半编译半解释型语言呢?它和C++的编译型语言和JavaScript解释型语言的差异到底在哪里?


????首先,我自己的一个误区理解为:

  • Java先通过javac将源文件编译为.class文件,但是.class文件并不能够直接执行,所以叫做半编译

  • 然后,再由JVM来解释执行.class文件,称为半解释型语言

半编译半解释就是.java 源文件编译了,但是不能够直接执行,故此得名。

❌但是,这是理解的误区。学到这里,才发现这样理解是错误的(但是老师是这么讲的,我也没深入探究)。


Java称为半编译半解释语言的根本原因,是:

执行引擎在解释执行字节码文件时,即可以使用解释器Interpreter来执行,又可以使用JIT( Just In Time Compiler)即时编译器来执行。所以叫半编译半解释型

【探究JVM八】Java的核心动力——执行引擎


JDK1.0时,将Java语言定位为“解释执行”是比较准确的。再后来, Java也发展出可以直接生成本地代码的编译器。

现在JWM在执行Java代码的时候,通常都会将解释执行与编译执行二者结合起来进行


TODO

  • 解释器的使用

  • 解释器与JIT的并存

  • 热点代码的探测确定

  • C1与C2编译器

  • AOT编译器