AJDK-AOT静态编译

很多云上的新应用不约而同地选择了 Go 语言,很大的原因是 Go 应用对运行时没有依赖,静态编译的程序启动速度快,也不需要通过 JIT 来预热。

Java 静态编译技术是一种激进的 AOT 技术,通过单独的编译阶段将 Java 程序编译为本地代码,在运行时无需传统 Java 虚拟机和运行时环境,只需操作系统类库支持即可。

静态编译技术实现了 Java 语言与原生 native 程序的“合体”,将原本的 Java 程序编译成为了一个自举的具有 Java 行为的原生 native 程序,由此兼有 Java 程序和原生 native 程序的优点。

Java编译原理:前端编译、即时编译(JIT编译)、静态提前编译(AOT编译)

1、前端编译

把Java源码文件(.java)编译成Class文件(.class)的过程;

也即把满足Java语言规范的程序转化为满足JVM规范所要求格式的功能;

优点:

*这阶段的优化是指程序编码方面的;
*许多Java语法新特性(“语法糖”:泛型、内部类等等),是靠前端编译器实现的,而不是依赖虚拟机;
*编译成的Class文件可以直接给JVM解释器解释执行,省去编译时间,加快启动速度;

缺点:

  • 对代码运行效率几乎没有任何优化措施;
  • 解释执行效率较低,所以需要结合下面的JIT编译;
  • 前端编译器:Oracle javac、Eclipse JDT中的增量式编译器(ECJ)等;

2、后端编译/即时JIT编译

通过Java虚拟机(JVM)内置的即时编译器(Just In Time Compiler,JIT编译器);在运行时把Class文件字节码编译成本地机器码的过程;

优点:

  • 通过在运行时收集监控信息,把"热点代码"(Hot Spot Code)编译成与本地平台相关的机器码,并进行各种层次的优化;
  • 可以大大提高执行效率;

缺点:

  • 收集监控信息影响程序运行;
  • 编译过程占用程序运行时间(如使得启动速度变慢);
  • 编译机器码占用内存;

JIT编译器:HotSpot虚拟机的C1、C2编译器等;

另外,JIT编译速度及编译结果的优劣,是衡量一个JVM性能的很重要指标;

所以对程序运行性能优化集中到这个阶段;

也就是说可以对这个阶段进行JVM调优;

3、静态提前编译/AOT编译

程序运行前,直接把Java源码文件(.java)编译成本地机器码的过程;

优点:

  • 编译不占用运行时间,可以做一些较耗时的优化,并可加快程序启动;
  • 把编译的本地机器码保存磁盘,不占用内存,并可多次使用;

缺点:

  • 因为Java语言的动态性(如反射)带来了额外的复杂性,影响了静态编译代码的质量;
  • 一般静态编译不如JIT编译的质量,这种方式用得比较少;

静态提前编译器(AOT编译器):JAOTC、GCJ、Excelsior JET、ART (Android Runtime)等;

关于ART (Android Runtime)模式:ART虽然主要通过AOT编译支持Java的运行,但仍然带有解释器

4、前端编译+JIT编译

目前Java体系中主要还是采用前端编译+JIT编译的方式,如JDK中的HotSpot虚拟机。

前端编译+JIT编译方式的运作过程大体如下:

1、首先通过前端编译把符合Java语言规范的程序代码转化为满足JVM规范所要求Class格式;

2、然后程序启动时Class格式文件发挥作用,解释执行,省去编译时间,加快启动速度;

3、针对Class解释执行效率低的问题,在运行中收集性能监控信息,得知"热点代码";

4、JIT逐渐发挥作用,把越来越多的热点代码"编译优化成本地代码,提高执行效率;

5、JIT和AOT对比

JIT:吞吐量高,有运行时性能加成,可以跑得更快,并可以做到动态生成代码等,但是相对启动速度较慢,并需要一定时间和调用频率才能触发 JIT 的分层机制

AOT:内存占用低,启动速度快,可以无需 runtime 运行,直接将 runtime 静态链接至最终的程序中,但是无运行时性能加成,不能根据程序运行情况做进一步的优化

JDK9的AOT

Java 9 引入了 aot 编译方式,能够将 class 文件直接编译成可执行二进制文件。

目前 JDK AOT 的局限有:

  • 仅支持 64 位 Linux 操作系统:;
  • 操作系统需要预装 libelf 库,以确保能够生成 elf 文件:
  • AOT 编译和执行环境需要相同:
  • Java 9 最初发布时,只支持 java.base 模块可以编译成 AOT 库;
  • 目前只支持 G1 和 Parallel GC 两种 GC 方式:前面没有提到,AOT 编译时的 JVM 参数和运行时需要相同,也包括 GC 方式,也就是说如果用了 AOT,JVM 实际运行时也只能使用这两种 GC 方式之一;
  • 可能会无法编译通过动态生成 class 文件或者修改字节码的 java 代码(如 lambda 表达式、反射调用等)
  • JVM 运行时参数设置必须和 AOT 库编译时相同;

AOT 可能带来的好处,是 JVM 加载这些已经预编译成二进制库之后,可以直接调用,而无需再将其运行时编译成二进制码。理论上,AOT 的方式,可以减少 JIT 带来的预热时间,减少 Java 应用长期给人带来的“第一次运行慢”感觉。

AJDK的AOT

JVM 团队与 SOFAStack 团队密切合作,在中间件应用上率先实现静态编译的落地。将一个应用的启动速度从 60 秒优化到 3.8 秒,双十一期间静态编译的应用运行稳定,没有故障, GC 停顿时间在 100 毫秒,在业务允许范围之内,内存占用和 RT 与传统 Java 应用持平。

综上所述,静态编译的应用在稳定性、资源占用、RT 响应等各方面指标与传统 Java 应用基本持平的状况下,将启动时间降低了 2000% 。

全部评论

相关推荐

头像
03-14 11:23
已编辑
北京邮电大学 管理咨询
211勇闯初创小公司头破血流系列3这件事不是发生在我身上的,但前同事们参与创作的积极性空前高涨,为了习惯,还是都采用第一人称的视角来看这出大戏。有一天老板在我们的眼皮底下接了一个电话,最终敲定了去北京出差的时间,下周一。他得意洋洋地说,这单下来保底五百万的流水,如果成了,我们都能得到五位数的提成。这对于一群刚上班的人来说是天大的诱惑,我们经历了周末的无偿加班,把他去北京所需要的文件都准备好了。只是在去北京的周一当天,老板睡过头了。整个上午都没见他的踪影,给他发文件也不会,打电话问问题也不接,直到中午才姗姗来迟。当然,这只是拉开了这场恐怖出差的序幕。只见他来了也不紧不慢的,手指在办公室转了一圈,...
姜大力:补充: 1.五百万的单子根本没有五百万,只是过去展示拼装的产品并简单考察。该项目只是竞标,项目内容是商业街区改造; 2.决策是当天上午10点半左右老板珊珊来迟后突发奇想去北京,中午1点在催促下着急出发,没有任何出差补助; 3.出发之前已经知道进京证不好使了,但还是执意要开车去; 4.实习生实打实连续开了***小事车,非常辛苦,工资在转正后只有两千五; (有疑问会继续补充)
点赞 评论 收藏
分享
评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客企业服务