java 机器码执行过程解析_从Java源代码到机器码

1. 编写Java源码

2. 通过javac命令对代码进行编译,得到.class字节码文件

我们之所要将Java源码变成Java字节码是因为,对于 Java 虚拟机来说,它想要得到的是字节码文件,而不是 Java 文件。

我们知道在 JDK 的安装目录里有一个 javac 工具,就是它将 Java 代码翻译成字节码,这个工具我们叫做编译器。相对于后面要讲的其他编译器,其因为处于编译的前期,因此又被成为前端编译器。我们运行 javac 命令的过程,其实就是 javac 编译器解析 Java 源代码,并生成字节码文件的过程。说白了,其实就是使用 javac 编译器把 Java 语言规范转化为字节码语言规范。javac 编译器的处理过程可以分为下面四个阶段:

第一个阶段:词法、语法分析。在这个阶段,JVM 会对源代码的字符进行一次扫描,最终生成一个抽象的语法树。简单地说,在这个阶段 JVM 会搞懂我们的代码到底想要干嘛。就像我们分析一个句子一样,我们会对句子划分主谓宾,弄清楚这个句子要表达的意思一样。

第二个阶段:填充符号表。我们知道类之间是会互相引用的,但在编译阶段,我们无法确定其具体的地址,所以我们会使用一个符号来替代。在这个阶段做的就是类似的事情,即对抽象的类或接口进行符号填充。等到类加载阶段,JVM 会将符号替换成具体的内存地址。

第三个阶段:注解处理。我们知道 Java 是支持注解的,因此在这个阶段会对注解进行分析,根据注解的作用将其还原成具体的指令集。

第四个阶段:分析与字节码生成。到了这个阶段,JVM 便会根据上面几个阶段分析出来的结果,进行字节码的生成,最终输出为 class 文件。

通过java命令将.class交给JVM

在这一步,有两种选择,一种是使用 Java 解释器逐行解释执行字节码,另一种则是使用 JIT 编译器将字节码转化为本地机器代码。

Java解释器

Java解释器启动速度快但运行速度慢,因为解释器不需要像 JIT 编译器一样,将所有字节码都转化为机器码(它直接逐行解释并执行字节码,不需要先转成机器码再执行),自然就少去了优化的时间。

JIT

JIT启动速度慢但运行速度快。当 JIT 编译器完成第一次编译后,其会将字节码对应的机器码保存下来,下次可以直接使用。而我们知道,机器码的运行效率肯定是高于 Java 解释器的。JIT 即时编译器,最常见的是 HotSpot 虚拟机中的 Client Compiler 和 Server Compiler,两种不同的编译器衍生出两种不同的编译模式,我们分别称之为:C1 编译模式,C2 编译模式。

C1 编译模式会将字节码编译为本地代码,进行简单、可靠的优化,如有必要将加入性能监控的逻辑。C2 编译模式,也是将字节码编译为本地代码,但是会启用一些编译耗时较长的优化,甚至会根据性能监控信息进行一些不可靠的激进优化。简单地说 C1 编译模式做的优化相对比较保守,其编译速度相比 C2 较快。而 C2 编译模式会做一些激进的优化,并且会根据性能监控做针对性优化,所以其编译质量相对较好,但是耗时更长。

实际上对于 HotSpot 虚拟机来说,其一共有三种运行模式可选,分别是:

混合模式(Mixed Mode) 。即 C1 和 C2 两种模式混合起来使用,这是默认的运行模式。如果你想单独使用 C1 模式或 C2 模式,使用 -client 或 -server 打开即可。

解释模式(Interpreted Mode)。即所有代码都解释执行,使用 -Xint 参数可以打开这个模式。

编译模式(Compiled Mode)。 此模式优先采用编译,但是无法编译时也会解释执行,使用 -Xcomp 打开这种模式。

在命令行中输入 java -version 可以看到,我机器上的虚拟机使用 Mixed Mode 运行模式。

AOT编译器

AOT 编译器的基本思想是:在程序执行前生成 Java 方法的本地代码,以便在程序运行时直接使用本地代码。

但是Java 语言本身的动态特性影响了Java 程序静态编译代码的质量。例如 Java 语言中的动态类加载,因为 AOT 是在程序运行前编译的,所以无法获知这一信息,所以会导致一些问题的产生。总的来说,AOT 编译器从编译质量上来看,肯定比不上 JIT 编译器。其存在的目的在于避免 JIT 编译器的运行时性能消耗或内存消耗,或者避免解释程序的早期性能开销。

在运行速度上来说,AOT 编译器编译出来的机器码比 JIT 编译出来的慢(注意是比JIT编译出来的机器码慢而不是AOT比JIT慢),但是比解释执行的快。而编译时间上,AOT 也是一个始终的速度。所以说,AOT 编译器的存在是 JVM 牺牲质量换取性能的一种策略。就如 JVM 其运行模式中选择 Mixed 混合模式一样,使用 C1 编译模式只进行简单的优化,而 C2 编译模式则进行较为激进的优化。充分利用两种模式的优点,从而达到最优的运行效率。

总结

fa5a9b6087e4

image.png

编译速度上,解释执行 > AOT 编译器 > JIT 编译器。

编译质量上,JIT 编译器 > AOT 编译器 > 解释执行。

实际情况中,为了运行速度以及效率,我们通常采用两者相结合的方式进行 Java 代码的编译执行。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值