浅谈Java开发技术的类型和模式(一)技术知识

【谈Java】主要是讲解Java开发的技术知识。它不会大而全面地详细讲解某项技术知识,而只是让你在短时间内毫无意外地学习或复习Java知识体系的叶子。

相关文档门户:

《论Java》五、同步中锁的获取与释放

《谈Java》六、自旋锁

《论Java》七、锁消除

《论Java》八、JVM的类型和模式(一)

《论 Java》9、JVM 类型和模式(二)

上一篇文章中介绍了编译器(Compiler)和解释器(Interpreter)。这在此处进行了更详细的解释。

一、编译器和解释器的职责

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

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

二、口译员:

解释器是 Java 虚拟机中非常重要的一部分。它的工作是将字节码转换为机器码并运行它。Hotspot 中实现了两个特定的解释器,即模板解释器和字节码解释器。

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

模板解析器:

实际上,解释器直接将字节码转换为汇编代码。当 JVM 初始化时,汇编器将汇编代码翻译成机器指令并将其加载到内存中。执行时只需要查找转发表即可实现字节码到机器码的翻译。

总之,HotSpot通过结合模板解释器和汇编器,结合线索寻址,大大提高了虚拟机的执行效率。

三、编译器:

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

前端编译器:将*.java 文件转换为*.class 文件的过程。比如JDK的Javac。Just In Time Compiler:Just In Time 编译器,通常被称为 JIT 编译器,是在“运行时”将字节码转换为本机机器码的过程。比如 HotSpot VM 的 C1、C2 编译器。Ahead Of Time Compiler:Ahead Of Time Compiler,通常称为AOT编译器,是将程序直接编译成与目标机器指令集相关的二进制代码的过程。比如JDK的Jaotc、GNU Compiler for the Java。

java中的前端编译器是javac命令。javac 在编译时进行词法分析、语法分析、语义分析和代码生成。最后将 *.java 文件转换为 *.class 文件。

前两篇文章中提到的编译器(JVM 1的Types and Modes and Types and Modes of JVM 2)基本上都是just-in-time编译器,属于java后端编译器。JIT作用于java应用运行周期.

为了提高热代码的执行效率,JVM会在“运行时”将这部分代码编译成本地机器码,并通过各种手段尽可能优化代码。在运行时执行此操作的后端编译器称为即时编译器

HotSpot VM 具有三个内置的即时编译器:

客户端编译器(Client Compiler),简称C1编译器。Server Compiler,简称C2 Compiler,或Opto Compiler。Graal 编译器(在 JDK 10 中,长期目标是取代 C2 编译器)。

C1编译器注重编译速度汇编语言转机器码工具,C2编译器注重编译质量。

当程序需要快速启动和执行时,解释器首先发挥作用汇编语言转机器码工具,节省编译时间并立即执行。程序运行后,随着时间的推移,编译器逐渐发挥作用。将越来越多的代码编译成原生代码后,可以获得更高的执行效率。

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

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

1:在程序运行前将程序代码编译成机器码的静态翻译工作。与JIT相比,它不占用运行时系统的大量资源;

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

四、总结

Java一直被称为解释型语言,主要是因为类文件字节码是由虚拟机解释执行的。并不是所有的 Java 虚拟机都使用解释器和编译器(这里是 JIT)共存的架构。可见解释器对java的重要性。

说JIT比解释快,其实是说“执行编译代码”比“解释和执行解释器”快,并不是说“编译”的动作比“解释”的动作快。只有对频繁执行的代码,JIT 编译才能保证正面的好处,否则效果是负面的。因为编译在运行时会占用系统资源,虽然编译后的代码可以被缓存。

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

【谈Java】本文是上一篇文章后半部分对编译器和解释器的描述。感谢阅读,请关注,点赞。随意喜欢并留下挥之不去的香味。学习非一日之寒,愿与大家一起鼓励。

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论