graalvm 想要一统天下嘛

一统天下的graalvm

可以先看一下这个图:
首先呢 对于jvm语言,graalvm想的是编译并运行
对于弱类型语言比如js,python graalvm 是用的一个truffle 框架解释并编译,然后运行

对于静态语言,c c++ 这种用的是llvm 静态编译

当然本系列文章主要是探讨graalvm 的native 功能,编程语言大致编译有如下两种

AOT:先编译后运行

JIT:有个解释器,直接解释运行

java 属于先编译成class 文件,然后解释运行,实现了一次编译处处运行

C/C++ 是属于编译运行,因此有了不同的平台不同的二进制文件

js:属于JIT 解释执行,所以平台无关

go:属于编译执行,但是带来vm

graalvm 打算做成go的这样子,就把jvm 和java代码打包在一起。一个二进制文件。因此他们也有不同平台的二进制

以前是xxx.java 通过javac 编译成xxx.class 然后在jvm 上解释执行xxx.class

graalvm 将xxx.java 直接变成二进制文件执行

graalvm起源

• 解释执行(Interpretation):初始阶段,JVM会对Java字节码进行解释执行,不生成本地机器代码,这使得程序可以立即运行。
• 即时编译(Just-In-Time Compilation):当某段代码(通常是被频繁执行的热点代码)被识别为性能瓶颈时,HotSpot JIT编译器将这些热点代码编译成本地机器代码。这个过程包括对代码进行优化,以提高执行速度。
• 本地机器代码执行(Execution of Native Code):一旦代码被编译成本地机器代码,JVM会直接执行这些代码,而不是再次解释执行对应的字节码。
java 的JIT 编译器为C1,C2。在Java早期阶段,存在两种类型的JIT(即时编译)编译器,分别是Client(客户端)和Server(服务器)。根据所需的JIT编译器类型,需要下载并安装相应的JDK。例如,如果您正在构建桌面应用程序,则需要下载具有“客户端”JIT编译器的JDK;如果是构建服务器应用程序,则需要下载具有“服务器”JIT编译器的JDK

java 热点数据会编译成二进制文件运行,那是不是都可以直接用C2 来编译成二进制文件呢?
这就是graalvm 的目前主要工作,实现java 代码的AOT编译

AOT编译的有哪些难点

1) 动态类型无法支持,只有静态类型才可以,所以js目前最多就ts可能有机会做到(dart 将动态类型改成了静态类型。go是采用的类型推断,本质还是静态类型)
2) 编译会很慢:因为要对齐类型对齐函数出入参,就导致了很多编译时的链接与查找 (但是后续的东西都是 测试JIT,运行AOT 类似flutter)
3) 空间会很大 至少一倍的差距,类似go,因为也打包了静态链接文件(例如jvm 和go runtime环境)
下面是打包后的对比 199M对比99M

-rwxrwxr-x 1 junlong junlong 199M 12月 26 17:57 target/snauth
-rw-rw-r– 1 junlong junlong 91M 12月 26 17:52 target/snauth-0.0.1-SNAPSHOT.jar

4) 动态字节码技术没了:很多为了实现动态代理及反射的优化。都会自动生成一份新的代码文件,来执行。由于aot编译类似c这种就无法实现。
5) 反射操作没了:java 的反射用在了很多很多地方,aot也无法实现,因为就得在编译时,告诉编译器,我反射用在哪些类上,用了哪个函数,让编译器手动把反射调用的给替换成真实调用的,这就是为啥反射越多,代码体积越大

AOT的主要好处:

1)启动速度很快
2)二进制编译代码安全,对比java 的反编译出来的东西,安全很多
3)内存占用和吞吐量会有很大提升
4)高性能,原生二进制编译时优化执行比解释时优化性能高不少


评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注