很多云上的新应用不约而同地选择了 Go 语言,很大的原因是 Go 应用对运行时没有依赖,静态编译的程序启动速度快,也不需要通过 JIT 来预热。
Java 静态编译技术是一种激进的 AOT 技术,通过单独的编译阶段将 Java 程序编译为本地代码,在运行时无需传统 Java 虚拟机和运行时环境,只需操作系统类库支持即可。
静态编译技术实现了 Java 语言与原生 native 程序的“合体”,将原本的 Java 程序编译成为了一个自举的具有 Java 行为的原生 native 程序,由此兼有 Java 程序和原生 native 程序的优点。
把Java源码文件(.java)编译成Class文件(.class)的过程;
也即把满足Java语言规范的程序转化为满足JVM规范所要求格式的功能;
优点:
*这阶段的优化是指程序编码方面的;
*许多Java语法新特性(“语法糖”:泛型、内部类等等),是靠前端编译器实现的,而不是依赖虚拟机;
*编译成的Class文件可以直接给JVM解释器解释执行,省去编译时间,加快启动速度;
缺点:
通过Java虚拟机(JVM)内置的即时编译器(Just In Time Compiler,JIT编译器);在运行时把Class文件字节码编译成本地机器码的过程;
优点:
缺点:
JIT编译器:HotSpot虚拟机的C1、C2编译器等;
另外,JIT编译速度及编译结果的优劣,是衡量一个JVM性能的很重要指标;
所以对程序运行性能优化集中到这个阶段;
也就是说可以对这个阶段进行JVM调优;
程序运行前,直接把Java源码文件(.java)编译成本地机器码的过程;
优点:
缺点:
静态提前编译器(AOT编译器):JAOTC、GCJ、Excelsior JET、ART (Android Runtime)等;
关于ART (Android Runtime)模式:ART虽然主要通过AOT编译支持Java的运行,但仍然带有解释器
目前Java体系中主要还是采用前端编译+JIT编译的方式,如JDK中的HotSpot虚拟机。
前端编译+JIT编译方式的运作过程大体如下:
1、首先通过前端编译把符合Java语言规范的程序代码转化为满足JVM规范所要求Class格式;
2、然后程序启动时Class格式文件发挥作用,解释执行,省去编译时间,加快启动速度;
3、针对Class解释执行效率低的问题,在运行中收集性能监控信息,得知"热点代码";
4、JIT逐渐发挥作用,把越来越多的热点代码"编译优化成本地代码,提高执行效率;
JIT:吞吐量高,有运行时性能加成,可以跑得更快,并可以做到动态生成代码等,但是相对启动速度较慢,并需要一定时间和调用频率才能触发 JIT 的分层机制
AOT:内存占用低,启动速度快,可以无需 runtime 运行,直接将 runtime 静态链接至最终的程序中,但是无运行时性能加成,不能根据程序运行情况做进一步的优化
Java 9 引入了 aot 编译方式,能够将 class 文件直接编译成可执行二进制文件。
目前 JDK AOT 的局限有:
AOT 可能带来的好处,是 JVM 加载这些已经预编译成二进制库之后,可以直接调用,而无需再将其运行时编译成二进制码。理论上,AOT 的方式,可以减少 JIT 带来的预热时间,减少 Java 应用长期给人带来的“第一次运行慢”感觉。
JVM 团队与 SOFAStack 团队密切合作,在中间件应用上率先实现静态编译的落地。将一个应用的启动速度从 60 秒优化到 3.8 秒,双十一期间静态编译的应用运行稳定,没有故障, GC 停顿时间在 100 毫秒,在业务允许范围之内,内存占用和 RT 与传统 Java 应用持平。
综上所述,静态编译的应用在稳定性、资源占用、RT 响应等各方面指标与传统 Java 应用基本持平的状况下,将启动时间降低了 2000% 。