从源代码到机器代码,Java语言中发生了什么?

本文详细介绍了Java源代码编译过程,包括Javac编译器的工作原理、JVM的编译阶段(词汇语法分析、符号表填充、注释处理和字节码生成),以及JIT编译器(如C1/C2编译模式)和AOT编译器的角色。讨论了不同编译器在速度和质量上的权衡以及JVM的混合模式应用。
摘要由CSDN通过智能技术生成

当我们使用纯文本编辑器打开演示时。类文件,我们将发现一系列16位的二进制流。

运行Javac命令的过程实际上是解析Java源代码并通过Javac编译器生成字节码文件的过程。直截了当地说,Java语言规范实际上是通过使用Javac编译器转换成字节码语言规范的。javac编译器的过程可以分为以下四个阶段:

第一阶段是词汇和语法分析。在这个阶段,JVM扫描源代码的字符一次,最后生成一个抽象语法树。简单地说,在这个阶段,JVM将理解我们的代码真正想要做什么。正如我们分析一个句子一样,我们将它分为主语、谓语和宾语,并找出句子的意思。

第二阶段:填写符号表。我们知道类彼此引用,但是在编译阶段,我们不能确定它们的特定地址,所以我们使用符号代替。我们在这个阶段所做的是类似的,即抽象类或接口的符号填充。加载类时,JVM用特定的内存地址替换符号。

第三阶段:注释处理。我们知道Java支持注释,所以在这个阶段,注释将根据注释的作用被分析并恢复到特定的指令集。

第四阶段:分析和字节码生成。在这个阶段,JVM将基于以上阶段的结果生成字节码,并且最终输出是一个类文件。

我们一般称 javac 编译器为前端编译器,因为其发生在整个编译的前期。常见的前端编译器有 Sun 的 javac,Eclipse JDT 的增量式编译器(ECJ)。

JIT 编译器:从字节码到机器码

当源代码转换为字节码时,有两种选择可以运行程序。一种是使用Java解释器来解释执行字节码,另一种是使用JIT编译器将字节码转换成本地机器代码。

两种方法的区别在于前者启动速度快,但运行速度慢,而后者启动速度慢,但运行速度快。原因很简单。因为解释器不需要像JIT编译器那样将所有字节码转换为机器代码,所以它自然地减少了优化时间。当JIT编译器完成其第一次编译时,它将保存与字节代码对应的机器代码,并且可以在下次直接使用。正如我们所知,机器代码必须比Java解释器更有效。因此,在实践中,为了更快、更有效地运行,我们通常结合这两种方法编译和执行Java代码。

HotSpot虚拟机内置了两个即时编译器,客户端编译器和服务器编译器。这两个不同的编译器派生了两种不同的编译模式,分别称为C1编译模式和C2编译模式。

注意:现在很多人都称客户端编译器C1编译器和服务器编译器C2编译器,但他们在Oracle官方文档中将其描述为编译器模式。所以C1编译器和C2编译器只是我们的习惯用语,而不是官方用语。这需要特别注意。

那么 C1 编译模式和 C2 编译模式有什么区别呢?

C1编译模式将字节码编译为本地代码,以便进行简单可靠的优化,并在必要时添加性能监视逻辑。C2编译模式也把字节码编译为本地代码,但是它能够进行一些需要长时间编译的优化,甚至是一些基于性能监视信息的不可靠的根本优化。

简单地说,C1编译模式相对保守,并且比C2快。C2编译模式会做一些根本性的优化,并且会基于性能监控做有针对性的优化,所以它的编译质量比较好,但是耗时。

那么到底应该选择 C1 编译模式还是 C2 编译模式呢?

实际上,对于HotSpot虚拟机,有三种操作模式,即:

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

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

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

从命令行输入Java版本,以查看我的机器上的虚拟机以混合模式运行。

到目前为止,我们已经学习了从Java源代码到字节码的整个过程,然后从字节码到机器代码。这应该已经在这里结束了,但是在我们的Java中有一个AOT编译器,它将源代码直接转换成机器代码。

AOT 编译器:源代码到机器码

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

然而,Java语言本身的动态特性带来了额外的复杂性,这影响了Java程序的静态编译代码的质量。例如,Java语言中的动态类加载,因为AOT是在程序运行之前编译的,它不能得到这些信息,因此会导致一些问题。还有许多其他类似的问题。这里没有例子。

通常,AOT编译器在编译质量方面肯定不如JIT编译器。它的目的是避免JIT编译器的运行时性能或内存消耗,或者避免解释器的早期性能开销。

就运行速度而言,AOT编译器编译的代码比JIT编译器慢,但比解释快。AOT在编译时间上也是一个恒定的速度。因此,AOT编译器的存在是JVM为了性能而牺牲质量的策略。正如JVM在其运行模式中选择Mixed模式一样,C1编译模式用于简单优化,而C2编译模式用于更彻底的优化。充分利用两种模式的优点,从而达到最佳的运行效率。

总结

JVM中有三个非常重要的编译器:前端编译器、JIT编译器和AOT编译器。

最常见的前端编译器是我们的Javac编译器,编译器将Java源代码编译成Java字节码文件。JIT即时编译器,最常见的是热点虚拟机中的客户端编译器和服务器编译器,将Java字节码编译成本地机器代码。AOT编译器可以直接将源代码编译为本地机器代码。这三个编译器的编译速度和质量如下:

  • 编译速度上,解释执行 > AOT 编译器 > JIT 编译器。
  • 编译质量上,JIT 编译器 > AOT 编译器 > 解释执行。
    在JVM中,通过这些不同方式的协作,可以优化JVM的编译质量和运行速度。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

最后,附一张自己面试前准备的脑图:

image

面试前一定少不了刷题,为了方便大家复习,我分享一波个人整理的面试大全宝典

  • Java核心知识整理

image

  • Spring全家桶(实战系列)

image.png

Step3:刷题

既然是要面试,那么就少不了刷题,实际上春节回家后,哪儿也去不了,我自己是刷了不少面试题的,所以在面试过程中才能够做到心中有数,基本上会清楚面试过程中会问到哪些知识点,高频题又有哪些,所以刷题是面试前期准备过程中非常重要的一点。

以下是我私藏的面试题库:

image

很多人感叹“学习无用”,实际上之所以产生无用论,是因为自己想要的与自己所学的匹配不上,这也就意味着自己学得远远不够。无论是学习还是工作,都应该有主动性,所以如果拥有大厂梦,那么就要自己努力去实现它。

最后祝愿各位身体健康,顺利拿到心仪的offer!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
主动性,所以如果拥有大厂梦,那么就要自己努力去实现它。

最后祝愿各位身体健康,顺利拿到心仪的offer!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值