aot的采坑记录
才使用aot的时候,可以说有很多的限制,有时候会发现一些不生效的过程,发现并没有使用上aot。这些都是大大小小的坑点。下面记录一下。下面会用到上次的一些素材,连接地址初识aot
启动参数固定化
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
发现是成功的。
启动的参数需要固定化这也就是说你有两种配置,就得先用jaotc去编译出两个版本的库,在用的时候进行选择。
编译参数和启动参数要一致
我们基于上面产生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的方法的。
class文件是必须存在
我们既然编译出可执行文件了,那么class文件是不是可以不要了呢。答案是不行的。我们下面用一个复杂一点的案例。
public class TestB{
public static void main(String[] args) {
System.out.println("this is TestB");
}
}
准备一个调用类。然后在另外一个文件里调用B。
public class AotTest{
public static void main(String[] args) {
TestB.main(null);
}
}
我们这次把B单独编译成库,依旧使用。
jaotc --output libB.so TestB.class
现在删除TestB.class,再次执行。我们发现会报下面的错误。
Exception in thread "main" java.lang.NoClassDefFoundError: TestB
at AotTest.main(AotTest.java:3)
Caused by: java.lang.ClassNotFoundException: TestB
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 1 more
直接是NoClassDefFoundError。
aot的理解
jvm的整体流程没有变化,aot的存在是替换了jit的部分,并不代表所有的数据都在生成的二进制文件里。aot并不是把java变成了例如c那种的可执行文件,他只是不需要动态的编译了,直接拿到现成的结果。
上一篇: kubernetes-----控制器
推荐阅读
-
aot的采坑记录
-
采坑记录
-
记录一个springcloud父子项目 子项目Consumer找不到其他项目的mapper或者自身和其他子项目的bean的坑
-
小白之安装nvm(windows版)踩过的坑记录
-
Jmeter分布式部署遇到的坑【记录】
-
记录自己走过的坑——egret.ScrollView
-
[ffmpeg]记录一下编译ffmpeg过程中的踩坑 博客分类: 视频编解码 ffmpeg
-
Spring Cloud Ribbon的踩坑记录与原理详析
-
Spring cloud踩坑记录之使用feignclient远程调用服务404的方法
-
记录安装Manjaro踩过的那些坑,解决安装后进入grub 的问题