Java 9 AOT初探

Java 9引入了 aot编译方式 ,能够将class文件直接编译成可执行二进制文件。目前Java 9的 early access版本 已经提供了编译工具,让我们来看看它的功能吧。

注意:按照JEP 295描述,目前版本的AOT,仅支持64位Linux操作系统。

jaotc使用

首先需要 下载 最新的Java 9(JDK),本文编写时,最新版本是Build 152。下载好的JDK只需要解压即可使用,特别注意使用前设置好 PATH 和 JAVA_HOME 两个环境变量,避免和机器上已经安装的JDK混淆。笔者安装到了$HOME/bin/jdk-9,并设置了:

export PATH=~/bin/jdk-9/bin:$PATH
export JAVA_HOME=~/bin/jdk-9

需要使用 jaotc ,首先需要有个测试类,首先从Hello World开始:

class HelloWorld {
        public static void main(String[] args) {
                System.out.println("Hello World!");
        }
}

代码非常简单,但是在执行jaotc之前,还需要将其编译成class文件,直接使用javac即可:

$ javac HelloWorld.java

执行成功之后,会生成HelloWorld.class文件。此时直接使用java命令,已经可以正常运行这个类:

$ java HelloWorld 
Hello World!

这时,就可以基于这个class文件,通过 jaotc 命令将其编译成二进制文件了。

$ jaotc --output libHelloWorld.so HelloWorld.class

如果一切正常,会生成libHelloWorld.so文件。

如果出现类似 Exception in thread "main" java.lang.UnsatisfiedLinkError: /home/babydragon/bin/jdk-9/lib/libjelfshim.so: libelf.so.1: 无法打开共享对象文件: 没有那个文件或目录 的错误,是因为 jaotc 需要依赖libelf动态链接库来创建 elf文件 (最终生成的libHelloWorld.so文件是一个静态链接的elf文件)。笔者使用的是Gentoo系统,需要安装dev-libs/elfutils包,以提供libelf.so这个动态连接库。安装之后可以通过 ldd 命令进行确认:

$ ldd $JAVA_HOME/lib/libjelfshim.so
        linux-vdso.so.1 (0x00007ffd001f3000)
        libelf.so.1 => /usr/lib64/libelf.so.1 (0x00007f25ea2ce000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f25e9f35000)
        libz.so.1 => /lib64/libz.so.1 (0x00007f25e9d1d000)
        /lib64/ld-linux-x86-64.so.2 (0x0000562318d51000)

前面通过 jaotc 命令成功生成了libHelloWorld.so。虽然命令里面参照JEP 295的示例将生成的文件后缀设置成了so,但如果使用 ldd 命令查看,会发现它其实是一个静态链接库:

$ ldd libHelloWorld.so 
        statically linked

通过 nm 命令,可以看见代码段中的函数入口:

$ nm libHelloWorld.so
0000000000002420 t HelloWorld.

  
   
 ()V
0000000000002520 t HelloWorld.main([Ljava/lang/String;)V

最后,需要执行时需要通过参数 -XX:AOTLibrary 参数指定需要加载的经过aot预编译好的共享库文件:

java -XX:AOTLibrary=./libHelloWorld.so HelloWorld

注意:虽然已经将整个HelloWorld类都通过jaotc编译成共享库文件,运行时仍然需要依赖原有的HelloWorld.class文件。

此时执行的输出,和之前不使用AOT的输出完全相同。

来把大的——将java.base模块编译成AOT库

JEP 295中已经说明,在Java 9初始发布的时候,只保证java.base模块可以被编译成AOT库。

继续参照JEP 295,创建java.base-list.txt文件,内容主要是排除一些编译有问题的方法,具体内容参照 原文 。

然后执行命令:

jaotc -J-XX:+UseCompressedOops -J-XX:+UseG1GC -J-Xmx4g --compile-for-tiered --info --compile-commands java.base-list.txt --output libjava.base-coop.so --module java.base

在笔者的机器上(i7-6600U + 16G内存 + 256G NVMe SSD),排除上述方法之后,编译时间大约为9分多钟。

48878 methods compiled, 4 methods failed (497771 ms)
Parsing compiled code (1126 ms)
Processing metadata (15811 ms)
Preparing stubs binary (0 ms)
Preparing compiled binary (104 ms)
Creating binary: libjava.base-coop.o (5611 ms)
Creating shared library: libjava.base-coop.so (7306 ms)
Total time: 542536 ms

完成之后,就可以使用AOT版本的java.base模块:

java -XX:AOTLibrary=java_base/libjava.base-coop.so,./libHelloWorld.so HelloWorld

同样,针对AOT,jvm也新增了参数打印哪些方法是通过加载AOT预编译库执行。

java -XX:+PrintAOT -XX:AOTLibrary=java_base/libjava.base-coop.so,./libHelloWorld.so HelloWorld

输出可以和不使用java.base的AOT进行比较,发现不使用java.base的AOT库,只能会加载libHelloWorld.so中对应的方法。

$ java -XX:+PrintAOT -XX:AOTLibrary=./libHelloWorld.so HelloWorld
     11    1     loaded    ./libHelloWorld.so  aot library
    105    1     aot[ 1]   HelloWorld.

  
   
 ()V
    105    2     aot[ 1]   HelloWorld.main([Ljava/lang/String;)V
Hello World!

$ java -XX:+PrintAOT -XX:AOTLibrary=java_base/libjava.base-coop.so,./libHelloWorld.so HelloWorld
     13    1     loaded    java_base/libjava.base-coop.so  aot library
     13    2     loaded    ./libHelloWorld.so  aot library
[Found  [Z  in  java_base/libjava.base-coop.so]
[Found  [C  in  java_base/libjava.base-coop.so]
[Found  [F  in  java_base/libjava.base-coop.so]
[Found  [D  in  java_base/libjava.base-coop.so]
[Found  [B  in  java_base/libjava.base-coop.so]
[Found  [S  in  java_base/libjava.base-coop.so]
[Found  [I  in  java_base/libjava.base-coop.so]
[Found  [J  in  java_base/libjava.base-coop.so]
     31    1     aot[ 1]   java.lang.Object.

  
   
 ()V
     31    2     aot[ 1]   java.lang.Object.finalize()V
...


输出太长,节选部分输出,我们可以看见java基础类及其方法都通过AOT的方式进行加载。

实用吗?

目前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应用长期给人带来的“第一次运行慢”感觉。

不过,本文使用的HelloWorld过于简单,无法通过对比得出AOT是否可以减少JVM初始化时间。笔者尝试对一个小型springboot应用进行AOT化,但是springboot框架本身无法在Java 9中运行。同时直接对spring-core的jar包执行jaotc也因为各种依赖问题而失败。

经过各种尝试,目前Java 9的AOT功能还处于很初步的阶段:

  • 缺少maven等管理工具集成,无法方便的对项目指定jar或者class文件比构建AOT库;
  • 大型框架还没有官方支持,构建AOT库难度比较高;
  • 大型框架如果直接提供AOT库,可能会因为由特定平台构建,而在本地无法使用;

期待Java 9正式发布的时候,能够对AOT有更好的支持。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: AOT是Ahead Of Time的缩写,意为预编译。WinForm是Windows Forms的简称,是一种用于Windows桌面应用程序开发的基于.NET框架的用户界面库。而AOT WinForm则是指使用预编译技术来加快WinForm应用程序的启动和执行速度。 以常规的编译方式,.NET应用程序通常需要在运行时对字节码进行JIT编译,这将导致启动时间和执行速度较慢。然而,AOT可以在应用程序打包时将所有字节码预先编译成本地机器代码,从而在运行时直接执行,这大大提高了程序的性能和响应速度。 在使用AOT WinForm时,开发者可以选择对整个应用程序或者部分组件(如DLL或EXE文件)进行预编译。虽然AOT编译可能需要更长的时间和更多的计算资源来完成,但通过减少JIT编译的时间和避免因为JIT编译而产生的性能损失,AOT可以为应用程序带来显著的优化效果。 总的来说,AOT WinForm是一种非常有用的优化技术,它可以提升WinForm应用程序的性能和响应速度,尤其是在需要处理较大数据量和复杂逻辑的情况下。 ### 回答2: AO.T是一家致力于培训人工智能人才的公司,其开发的AO.T Winform是一款基于.NET Framework技术的窗体应用程序。WINFORM是WINDOWS FORMS的缩写,指的是Windows桌面应用程序。具有易于编写和使用、可多种控件设计和使用和可快速开发的特点,适用于各细分行业。AO.T Winform实现了窗口设计中各控件的灵活布局和操作,它可以简化Windows应用程序开发过程,同时通过提供免费的软件授权来降低企业的成本。 AO.T Winform支持在Windows上开发GUI应用程序,并且由于采用.NET技术,因此它可以使用C#或VB.NET等编程语言进行开发。它也提供了一系列的用户界面的控件和容器,比如TextBox文本框、Button按钮、Label标签、ComboBox下拉菜单、DataGridView表格控件以及各种面板和容器来帮助用户快速开发完整的应用程序。 AO.T Winform对于初学者来说是一款非常好的学习工具。学生可以用它来学习GUI编程、面向对象编程、事件驱动等技术,还可以通过练习来提高自己的编程能力,以及掌握多种常用的技巧,例如自定义控件和定制窗口等。 总之,AO.T Winform是一款灵活、易于使用、快速开发的GUI工具,可以帮助企业降低开发成本,还能够帮助学生快速掌握GUI编程,提高自己的编程水平。 ### 回答3: AOI(自动光学检查)技术在现代制造业中被广泛使用,可以帮助生产厂家在制造过程中快速准确地检查电路板的质量,提高生产效率和质量。AOI技术依赖于高精度的图像分析算法,需要可靠的软件平台来实现。 AOT WinForm是一款专门为AOI应用开发的图形用户界面(GUI)开发工具。它提供了多种开发组件、图形控件和功能模块,可以快速构建高效的AOI检测软件。使用AOT WinForm,开发者可以轻松地实现各种检测算法,包括PCB元器件安装检测、焊点检测、短路检测、开路检测、电路板外形检测等。与传统的手工检测方式相比,AOT WinForm可以大大提高检测速度和精度,降低生产成本和人力投入。 AOT WinForm具有以下优点: 1. 可视化的设计界面:AOT WinForm提供了友好的可视化设计界面,不需要编写复杂的代码就可以创建出漂亮的GUI界面,可以大大提高开发效率。 2. 高效的算法库:AOT WinForm内置了丰富的图像处理和算法库,包括常用的图像变换、边缘提取、滤波等算法,可以快速实现多种电路板检测功能。 3. 全面的支持:AOT WinForm支持多种数据接口和格式,可以与各种数据源集成,包括网络摄像头、CCD相机、扫描仪等。 4. 易于维护和升级:由于AOT WinForm使用标准的.NET框架和C#语言,因此易于维护和升级,开发者可以根据需要自由扩展和修改代码。 总之,AOT WinForm是一个高效、可靠的AOI开发工具,可以帮助电路板制造商提高生产效率和质量,加快新产品上市时间,降低生产成本。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值