14 HotSpot虚拟机将字节码编译为机器码的过程


特别说明:

  1. 本章内容基于HotSpot虚拟机

    1. 编译器指HotSpot内置的即时编译器
    2. 虚拟机指HotSpot
  2. 机器码:能够被被当前机器直接执行的代码,机器属于某个平台:SPARC、x86-AMD64、ARMv8-AArch64

1 广义理解:解释执行与编译执行

阅读原文2天,我仍然没理解 什么是解释执行,跟编译执行有什么不同。我尝试从书籍原文和行业规范等方向去查找资料,可是效果不佳。无奈,只能找一篇看起来还算正规的文章,以不思考通篇接受的方式,来帮助自己理解解释执行。这小节内容整理自:3分钟搞懂什么是编译执行和解释执行

2 HotSpot虚拟机基本介绍

  1. 它是Sun/OracleJDK和OpenJDK中的默认Java虚拟机,也是目前使用范围最广的Java虚拟机,首次被应用在JDK 1.3;
  2. 内置有编译器和执行器,采用解释器与编译器并存的运行架构
  3. 对比其他虚拟机,核心技术有:热点代码探测技术

3 为何HotSpot虚拟机要使用解释器与即时编译器并存的架构?

  1. HotSpot执行字节码三种方式:

    1. 解释执行:解释器逐条执行字节码指令,或者轻度优化字节码后再执行
    2. 编译执行:即时编译器先对字节码指令流深度优化,编译成机器码后再执行。
    3. 混合模式:解释器和编译器协同执行
  2. 解释器和编译器如何协同工作:

    1. 程序启动时,先启用解释器,省去编译的时间,立即运行。
    2. 程序启动后,启用编译器,把越来越多的代码编译成本地代码,这就减少解释器的中间损耗,获得更高的执行效率。
    3. 如果编译器优化失败,还能退回解释器执行【这叫逆优化】
  3. 协同目的:

兼顾程序响应时间执行性能,而且无须等待本地代码输出才能执行程序,即时编译的时间压力也相对减小,这样有助于引入更复杂的代码优化技术,输出质量更高的本地代码。

4 为何HotSpot虚拟机要实现两个(或三个)不同的即时编译器?

  1. 内置了三个即时编译器:

    1. 2个传统的:客户端编译器(C1)、服务端编译器(C2),
    2. 1个JDK10出现的:Graal编译器(长期目标是代替C2)
  2. 解释器搭配一个编译器来工作:

    1. 默认:HotSpot根据自身版本与宿主机的硬件性能自动选择编译器
    2. 指定:使用 -client-server参数来指定编译器
  3. 目的:因为不同的编译器,优化的深度不一样,用户可以根据程序特点来选择

5 程序何时使用解释器执行?何时使用编译器执行?

  1. HotSpot工作模式:

    1. 默认采用混合模式
    2. -Xint强制使用解释模式:编译器不工作,全部指令都使用解释方式执行
    3. -Xcomp强制使用编译模式,优先采用编译方式执行程序,但是解释器仍然要在编译无法进行的情况下介入执行过程
    4. 不同参数运行结果:
  2. 引入分层编译原因:

    1. 即时编译器越优化,耗时越长
    2. 编译器优化时,解释器要替编译器收集性能监控信息,反倒影响解释执行阶段的速度
    3. 兼顾程序启动响应速度运行效率之间达到最佳平衡,引入分层编译
  3. 分层编译层次:

    • 第0层。纯解释执行,且解释器不开启性能监控功能
    • 第1层。C1将字节码编译为本地代码来运行,进行简单、可靠优化,不开启性能监控。
    • 第2层。C1执行,仅开启方法及回边次数统计等有限的性能监控功能
    • 第3层。C1执行,开启全部性能监控,除了第2层的统计信息外,增加收集 分支跳转、虚方法调用版本等统计信息。
    • 第4层。C2将字节码编译为本地代码,对比C1,C2会启用更多编译耗时更长的优化,并根据性能监控信息进行一些不可靠的激进优化

6 哪些程序代码会被编译为本地代码?如何编译本地代码?

  1. 即时编译器编译的目标是热点代码:(以方法为单位)

    • 被多次调用的方法
    • 被多次执行的循环体
  2. 客户端编译器的三段式编译过程:

  3. 服务端编译器的编译过程:

    1. 比客户端模式进行更深入的优化:无用代码消除、循环展开、循环表达式外提、消除公共子表达式、常量传播、范围检查消除、空值检查消除;不稳定的预测性激进优化:守护内联、分支频率预测
    2. 采用全局图着色寄存器分配器
    3. 它更,但是输出代码的质量更高
  4. 即时编译目的

    1. 将字节码翻译为机器码 【基本、简单的需求】
    2. 代码优化【核心、关键的需求】

7 如何从外部观察到即时编译器的编译过程和编译结果?

算了吧,太复杂。

8 总结

回归主题,HotSpot虚拟机将字节码编译为机器码过程,如下图所示:

字节码转机器码补充说明:

  1. HotSpot预先写好所有字节码指令对应的汇编命令函数集,以字节码指令为key,函数为value方式保存
  2. HotSpot的模板解释器根据字节码指令查找到对应的汇编命令函数【查表方式】,不同平台的汇编器将这些汇编命令翻译成各自平台的机器码。

综上,编译过程总结过:原始字节码-->HotSpot优化字节码-->优化后的字节码翻译成机器码-->以编译执行方式运行程序。

posted @ 2022-12-12 23:59  拿了桔子跑-范德依彪  阅读(252)  评论(0编辑  收藏  举报