aot上手

aot介绍

aot是Ahead-Of-Time的缩写,以前大家都知道java的一个定位就是半编译,半解释型语言。他把java文件编译成class文件,最后jvm解释执行class文件,jvm可以把class文件解释为对应的机器码,这个就是靠的jit。aot则是直接把class文件编译系统的库文件,不在依靠jit去做这个事情。并不是说编译好本地库以后,原来的class就可以不要删除了。

demo环境

要求版本
系统macos
javajdk11
本地编译xcode11

这里提到了系统和编译器。可以说写c需要什么,这里就需要准备什么,简单点的话,最好准备和系统配套的编译器,减少编译的坑。

java代码


public class AotTest{
    public static void main(String[] args) {
        System.out.println("first aot");
    }
}

平平无奇,和我们普通写java一样。 编译java文件

 javac AotTest.java

平平无奇,和我们平时编译也没区别。 开始编译成本地库

jaotc --output libtest.so AotTest.class

jaotc是jdk提供的编译成本地库的方式。他和java一样,在bin目录下,如果配置了环境变量,是可以执行的。 如果系统和编译器匹配,这里就是一把过。最终会在本地生成libtest.so的文件。 开始执行

 java -XX:AOTLibrary=./libtest.so AotTest

编译成本地库,我们也还是要指定一下main的类,这个和以前java -cp执行没有区别。

first aot

不出意外可以执行方法。 你一定也发现了,这个操作很繁琐,这还是一个文件,要是编译出来的class特别多,怎么办。而且还没有管理的工程文件。 这点jdk已经帮我们想到了。

 jaotc
Usage: jaotc <options> list

  list       A : separated list of class names, modules, jar files
             or directories which contain class files.

where options include:
  --output <file>            Output file name
  --class-name <class names> List of classes to compile
  --jar <jarfiles>           List of jar files to compile
  --module <modules>         List of modules to compile
  --directory <dirs>         List of directories where to search for files to compile
  --search-path <dirs>       List of directories where to search for specified files
  --compile-commands <file>  Name of file with compile commands
  --compile-for-tiered       Generate profiling code for tiered compilation
  --compile-with-assertions  Compile with java assertions
  --compile-threads <number> Number of compilation threads to be used
  --ignore-errors            Ignores all exceptions thrown during class loading
  --exit-on-error            Exit on compilation errors
  --info                     Print information during compilation
  --verbose                  Print verbose information
  --debug                    Print debug information
  -? -h --help               Print this help message
  --version                  Version information
  --linker-path              Full path to linker executable
  -J<flag>                   Pass <flag> directly to the runtime system

查看帮助文档,发现他支持的扫描方式多种多样,最简单的方式,我们依旧使用maven编译,最后打成的jar包。通过--jar参数来生成库文件。

启动参数固定化

jaotc可以通过加-J参数来指定jvm的启动参数。 我们尝试使用cms来编译一下库文件。

jaotc   -J-XX:+UseConcMarkSweepGC --output libtest.so AotTest.class

执行的结果会有两条信息。

Java HotSpot(TM) 64-Bit Server VM warning: Option UseConcMarkSweepGC was deprecated in version 9.0 and will likely be removed in a future release.
Error occurred during initialization of VM
JVMCI Compiler does not support selected GC: concurrent mark sweep gc

第一条是cms已经标记为废弃。第二条是jvmci不支持cms。 按照官方文档上讲,现在的aot支持ps和g1。其他的并不支持。 我们下面试试ps,因为现在默认已经是g1了。

jaotc   -J-XX:+UseParallelGC --output libtest.so AotTest.class

发现是成功的。 我们基于上面产生ps的libtest.so,我们尝试换个启动参数。

java  -XX:+UseConcMarkSweepGC -XX:AOTLibrary=./libtest.so AotTest
java  -XX:+UseParallelGC -XX:AOTLibrary=./libtest.so AotTest
java  -XX:+UseG1GC -XX:AOTLibrary=./libtest.so AotTest

你会发现上面三个启动参数都会执行正确,并没有报错。 是不是感觉违背了官方讲的编译和启动一致的这个要求。 这里介绍一个参数。

-XX:+PrintAOT

这个参数可以打出使用aot的klasses和method。我们下面再试试G1(库是上面指定了ps的)。

java  -XX:+UseG1GC -XX:+PrintAOT -XX:AOTLibrary=./libtest.so AotTest

我们会发现有不一样的输出。

Shared file ./libtest.so error: used 'parallel gc' is different from current 'g1 gc'
      7    1     skipped ./libtest.so  aot library

这里会有一个错误提示,说libtest.so是使用了ps和现在用的g1不一样。跳过了这个库。 然后对比一下ps的结果。

     12    1     loaded    ./libtest.so  aot library
    113    1     aot[ 1]   AotTest.<init>()V
    113    2     aot[ 1]   AotTest.main([Ljava/lang/String;)V

发现ps是可以打印出aot的方法的。

合理设置参数

jaotc可以使用-J指定运行时参数,官方的例子中使用了gc参数和压缩指针参数。

jaotc   -J-XX:-UseCompressedOops --output libtest.so AotTest.class

如果运行时没有-XX:-UseCompressedOops日志中会打印出一个异常。

Shared file ./libtest.so error: UseCompressedOops has different value 'false' from current 'true'
    832    1     skipped ./libtest.so  aot library

gc的也同理。 哪些运行时参数是必须编译时就设置的,这个我自己测试了-Xmx这些,是可以运行的。现在发现的其实就是那两个参数,这个只能说实践中慢慢确认了。 这里也就是出现了一个问题,我们的程序不一定都要用G1,有的也需要使用ps,堆小的是需要开启压指针的,堆大的确实不需要。针对这种情况,我们能做的就是把情况和组合枚举一下,然后编译出多个版本,启动的时候指定不同的版本,官方就推荐这么做的,甚至他还举了例子。

-XX:-UseCompressedOops -XX:+UseG1GC :       libjava.base.so
-XX:+UseCompressedOops -XX:+UseG1GC :       libjava.base-coop.so
-XX:-UseCompressedOops -XX:+UseParallelGC : libjava.base-nong1.so
-XX:+UseCompressedOops -XX:+UseParallelGC : libjava.base-coop-nong1.so

应该庆幸参数可能就这么少,如果运行时特别多的话,编译起来估计要疯的,得写脚本做循环遍历。然后用的时候得按照规则加载出合适的库,大部分时间都花在了脚本匹配上了,而且还得打开-XX:+PrintAOT,这个错误并不会让程序失败停止。还需要做日志分析。所以说这个用起来确认正确性还真是一个麻烦的事情。

动态注入

如果使用了-javaagent加入的监控修改了字节码会是什么表现呢? 我们使用了字节码注入的agent demo。下面是个开源版本。 注入agent 这里一定要注意一个点,这个工具是通过asm做的,他可以打印方法的运行时间。**使用时要把asm的jar包换成一个对应jdk的版本,目前项目用的6,java11得升级。**否则你会发现神奇的错误,那个错误妙不可言。

java -Xbootclasspath/a:asm-8.0.1.jar:asm-analysis-8.0.1.jar:asm-commons-8.0.1.jar:asm-tree-8.0.1.jar  -javaagent:trace-0.0.1-SNAPSHOT-agent.jar=Test -XX:AOTLibrary=./libtest.so -XX:+PrintAOT AotTest

通过这个启动参数。我这里只注入我的一个测试类。看看他的方法打印的结果,以及aot的表现。 加agent日志

    179    1     aot[ 1]   AotTest.lambda$main$0(II)I
    179    2     aot[ 1]   AotTest.<init>()V
this is TestB 
[Ljava.lang.String; main cost 0(这里是agent输出,单位是毫秒)

不加agent

     11    1     loaded    ./libtest.so  aot library
    107    1     aot[ 1]   AotTest.lambda$main$0(II)I
    107    2     aot[ 1]   AotTest.<init>()V
    107    3     aot[ 1]   AotTest.main([Ljava/lang/String;)V
    108    4     aot[ 1]   TestB.<init>()V
    108    5     aot[ 1]   TestB.main([Ljava/lang/String;)V
this is TestB

结果发现testB不见了,也就是说agent注入改造后的类是无法使用aot的效果的。

小结

java发展这么多年了,大家也没有感觉jit有什么不好的,为什么还要加入aot呢。 我们如果对比jit和aot,可以发现一些区别,就是aot已经编译成本地代码了,不用再靠jvm进行解释执行,这样省去了jvm的解释时间。换句话说启动更快了。 启动更快的这个需求,可以说是伴随云原生的。我们设想以下的场景。web服务进行促销业务,结果发现流量比预期的多,刚来时就达到了警戒线,因为是突发,所以增长速度要比原来快。此时启动一个程序花了5s,那么就得有5s的风险去承担流量冲击,很可能把服务冲垮了,如果1s就可以启动成功,那么风险就会大大减小。 aot肯定不完全都是好的,跨平台的特性首选去除了。其次aot最终运行效果是不如jit的。jit因为在运行时进行分析,所以更好的了解程序的运行,aot则不能,所以启动更快,但是巅峰的运行速度,可能是略差与jit的。并且为了编译成功,依赖的jar包必须都全部在,例如编译A,那么A依赖的库必须都在,否则编译会失败,反射,aop等动态的特性都会有问题。A依赖B里的一个逻辑,B的方法里依赖了C,jit只有在方法调用的时候才会触发类加载等,A调用的方法里不用C,C是可以不加入的。但是编译成本地库则不能,不管用不用,依赖就得在。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答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开发工具,可以帮助电路板制造商提高生产效率和质量,加快新产品上市时间,降低生产成本。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值