✅什么是AOT编译?和JIT有啥区别?

典型回答

我们都知道,Java中有两种编译方法:

1、javac把java代码编译成字节码,然后由Java虚拟机解释执行。

2、JIT把java代码直接编译成机器码,然后由Java虚拟机直接运行。

✅简单介绍一下JIT优化技术?

但是,JIT编译有一些比较明显的缺点也是不能忽视的:

  1. 增加启动时间:由于JIT编译器在程序运行时编译代码,它可能导致应用程序的启动时间较长。
  2. 可能会影响应用性能:JIT编译是需要进行热点代码检测、代码编译等动作的,这些都是要占用运行期的资源,所以,JIT编译过程中也可能会影响应用性能。

而在如今的云原生盛行的今天,应用的快速启动以及减少预热时长是非常重要的,其实是Serverless场景中,所以,个新兴的编译器GraalVM就诞生了。他提出了一种新的编译方式——Ahead of Time,及AOT编译。

✅为什么云原生对应用的启动速度要求很高?

AOT编译,翻译一下就是提前编译,它不像JIT一样在运行期才生成机器码,而是在编译期间就将字节码转换为机器码,这就直接省去了运行时对JVM的依赖。这是一种典型的静态编译技术。

java 静态编译,是指将java程序的字节码在单独的离线阶段编译为汇编代码,它的输入是Java的字节码,输出是native image。

这里多说一句,很多人会误以为编译期的编译不是javac吗?其实javac只是把源代码(.java)编译成中间代码(.class),这种中间代码我们叫做字节码,而字节码并不是机器代码,无法直接执行,需要解释器进行解释执行。详见:

✅Java是编译型还是解释型?

因为AOT编译是在编译期就生成机器代码了,所以,应用启动时就不需要编译,那么他就可以大大的减少应用的启动时间,提升系统的整体性能。所以他非常适用于对启动时间敏感的场景,例如云原生应用。

1705410553249-a34b25c4-32a6-46bc-81e9-8a2a9ea82aa2.png

扩展知识

静态编译的优势

与传统的Java的运行时编译(动态编译/jit)相比,静态编译主要有几个重要的优势:

1、机器执行的时候执行的是经过编译优化的本地代码。执行本地代码可以非常的高效和快速,并不需要进行解释执行和JIT编译,就可以直接执行。

2、静态编译后的可执行程序自包含了轻量级运行时支持,所以他在运行时不再需要依赖额外的JVM。

3、解决应用程序的冷启动问题。有了静态编译后的本地代码,应用程序就可以快速地启动,不再解释执行,也不再需要JIT的预热。

4、打破Java程序与本地代码之间的边界。因为编译后的代码也是本地代码,所以JNI调用的开销更低了。

静态编译的局限性

封闭性假设

一个Java程序之所以能做静态编译,需要满足一个至关重要的前提——封闭性假设

什么是封闭性假设,也就是说他要求所有运行时的内容必须在编译时可见,并且可以被编译到native image中。但是Java中有很多代码是没有办法在编译期就确定的,比如反射,他就是不满足封闭性假设的。

其他的类似的违反封闭性假设的特性还有动态代理、序列化、JNI、动态类加载等等。所以,遇到这些代码的时候,就需要额外的适配来解决。带来了很多的复杂性,也给静态编译带来了一定的局限性。

平台相关性

Java有一个很重要的特性就是平台相关性,但是随着静态编译的盛行,这个说法已经并不一定就成立了。

静态编译以后的代码程序,其实就是平台相关的了。

✅Java一定就是平台无关的吗?

原文: https://www.yuque.com/hollis666/xkm7k3/cy5i6guhszisviks