您的位置 首页 java

「浅谈Java」十,编译器与解释器


相关文档传送门:

在前面文章介绍过编译器(Compiler)和解释器(Interpreter)。在这里针对此做更详细的说明。

一,编译器与解释器职责

编译器:负责生成 字节码 文件。 Java编译器 读取java源文件(*.java)并将它们编译为java字节码文件(*.class)。

解释器 :负责运行字节码文件。Java编译器生成的是与机器码不同的java字节码,并不能被硬件中的 CPU 直接执行。而java解释器就像植根于软件中的CPU,能够解析并执行java字节码。

二,解释器:

解释器是 Java虚拟机 非常重要的一部分,它的工作就是把字节码转化为机器码并运行。 Hotspot中实现了两种具体的解释器,分别是模板解释器和字节码解释器。

字节码解释器 没有编译优化,效率比较低,本质上就是一个比较长的switch语句,针对不同的字节码执行不同的操作。目前JVM虽然保留字节码解释器 却没有使用。

模板解析器:

  • 1,为每个字节码创建模板;
  • 2,用模板为每个字节码生成对应的机器指令;
  • 3,每个字节码生成的机器指令地址存储在派发表中;
  • 4,每个字节码生成的机器指令末尾,插入自动跳转下条指令逻辑

其实解释器直接把字节码 转化成汇编代码, 在JVM初始化时, 汇编器 会将汇编代码翻译成机器指令加载到内存中。 执行的时候只需要查转发表就可以实现字节码到机器码的翻译。

总之HotSpot通过将模板解释器与汇编器联合在一起工作,结合线索寻址将 虚拟机 的执行效率大幅提升。

三,编译器:

Java 技术中的编译器可以分为如下三类:

  1. 前端编译器:把 *.java 文件转变为 *.class 文件的过程。比如 JDK Javac
  2. 即时编译器:Just In Time Compiler,常称 JIT 编译器 ,在「运行期」把字节码转变为本 地机器码的过程。比如 HotSpot VM 的 C1、C2 编译器。
  3. 提前编译器:Ahead Of Time Compiler,常称 AOT 编译器,直接把程序编译成与目标机 器指令集相关的 二进制 代码的过程。比如 JDK 的 Jaotc,GNU Compiler for the Java。

java中前端编译器 就是javac命令。javac在编译时会经历 词法分析、语法分析、语义分析和代码生成。最终把 *.java 文件转变为 *.class 文件。

笔者在前面两篇文章 (JVM的类型和模式1和JVM的类型和模式2)中说的编译器基本上都是即时编译器,归属于java后端编译器。JIT作用于java应用的运行期。

为了提高热点代码的执行效率,JVM 会在「运行时」把这部分代码编译成本地机器码,并以各种手段尽可能地进行代码优化。运行时完成这个任务的后端编译器被称为 即时编译器

HotSpot VM 内置了三个即时编译器,分别为:

  1. 客户端编译器(Client Compiler),简称 C1 编译器。
  2. 服务端编译器(Server Compiler),简称 C2 编译器,或 Opto 编译器。
  3. Graal 编译器(JDK 10 出现,长期目标是替代 C2 编译器)。

C1编译器注重编译的速度,C2编译器注重编译的质量。

当程序需要迅速启动和执行的时候,解释器首先发挥作用,省去编译的时间,立即执行。在程序运行后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,可以获取更高的执行效率。

当程序运行环境中内存资源限制较大(如部分 嵌入式系统 中),可以使用解释器执行节约内存,反之可以使用编译执行来提升效率。此外,如果编译后出现“罕见陷阱”,可以通过逆优化退回到解释执行。例如当JVM进行激进优化时需要一个“逃生门”,通常由解释器担任,职责是在激进优化失败后继续完成任务。

提前编译器(Ahead Of Time Compiler,AOT编译器) :直接把程序编译成与目标机器指令集相关的二进制代码的过程。主要两种方式 :

1:在程序运行之前把程序代码编译成机器码的静态翻译工作。相对于JIT而言不用占用运行期系统大量资源;

2:就是“热点代码”的动态提前编译。HotSpot运行时可以直接加载这些编译结果,实现快速程序启动速度,减少程序达到全速运行状态所需要的时间。

四,总结

java一直以来被说是一门解释执行的语言,主要是因为由虚拟机解释执行 class文件 字节码。 而且并不是所有的Java虚拟机都采用解释器与编译器(这里是JIT)并存的架构。可见解释器对于java的重要性。

说JIT比解释快,其实说的是“执行编译后的代码”比“解释器解释执行”要快,并不是说“编译”这个动作比“解释”这个动作快。只有对频繁执行的代码,JIT编译才能保证有正面的收益,否则效果为负。因为编译会占用运行期的系统资源,尽管编译后的代码可以缓存。

如果代码先提前编译是不是运行效果更好呢?这就是C或C++了,不是java了,JVM执行引擎(Execute Engine)是解释器 + JIT编译器。使用JIT是基于性能分析制导优化。通俗的说JVM在运行的过程中,会不断收集性能监控信息,这些信息可以帮助 JIT 编译器对“热点代码”和循环块进行集中优化。这一点在 静态分析 时是很难做到的。

【浅谈Java】本文是上一篇文章的后面一段编译器与解释器的说明。感谢阅读,求关注,求点赞。随手点赞,留有余香。学习是冰冻三尺非一日之寒,愿与诸君共勉励。

文章来源:智云一二三科技

文章标题:「浅谈Java」十,编译器与解释器

文章地址:https://www.zhihuclub.com/199572.shtml

关于作者: 智云科技

热门文章

网站地图