【JVM深度系列】“云原生Java虚拟机”对GraalVM的重塑与探索对于Python,微服务趋势对于Golang等等。大家都知道,任何一种语言不可能在每个领域都有优势。Java已经是最接近这个目标的选择,但如果“不行”,你只能忘记Java语言本身,步入无招取胜的境界。进一步提高运行在JVM上的程序的性能CompileJava通过预编译(ahead-of-time)将程序转化为原生可执行程序多种编程语言混合在一个程序中(多语言)与LLVM类似,GraalVM也提供了便利机制,方便开发新的编程语言。目前的痛点是在云原生时代,Java程序有很大的劣势,为什么这么说呢?一般的Java应用需要几十兆的内存,而且启动速度不快。以目前最流行的SpringBoot/SpringCloud微服务框架为例例子,优化过的应用启动至少需要3-4秒,很多bean需要lazyload,内存需要上百兆,业务逻辑稍微复杂一点,没有超过1G。内存难以满足业务需求?那么在云原生时代,给大家介绍了一个充满黑科技的JVM,可以帮助我们将Java程序的启动速度提高100倍,而且只需要原来内存的五分之一,甚至更少。Graalvm简介GraalVM是Oracle在2018年开发的下一代JVM实现,官方称为“UniversalVM”和“PolyglotVM”。这是在HotSpot虚拟机的基础上增强的跨语言全栈虚拟机。用作“任何语言”的运行时平台。这里的“任何语言”包括Java、Scala、Groovy、Kotlin等基于Java虚拟机的语言,以及C、C++、Rust等基于LLVM的语言,同时支持其他语言如JavaScript、Ruby、Python和R等。GraalVM可以在不增加额外开销的情况下混合使用这些编程语言,支持使用不同语言的接口和彼此的对象,也可以支持这些语言使用已经编写好的原生库文件。它的口号“RunProgramsFasterAnywhere”可以让人感受到勃勃的雄心壮志。与GraalVM的性能相比,Graalvm的性能确实不错。以JDK8为例OpenJDKOracleJDK。OpenJDK通过“GPLv2withCE”协议开源,可免费用于商业用途。之前使用ApacheSpark测试性能的时候,比较一下两者的性能。对于数据量稍大的查询,你会发现OracleJDK一般比OpenJDK快30%以上。GraalVM分为社区版和商业版,其中GraalVM的社区版也是开源的,使用与OpenJDK相同的“GPLv2withCE”协议。对于社区版的GraalVM,我惊喜地发现它也比OracleJDK快了10%以上。我还没有尝试过GraalVM的商业版本。据官方报道,商业版比社区版对性能的提升更大。Graalvm的主要特点是高性能的现代Java,占用资源少,启动速度快。JavaScript、Java、Ruby和R混合编程运行在JVM上原生语言跨语言工具JVM应用扩展原生应用扩展本地Java库数据库支持多种语言Graalvm工作原理GraalVM的基本工作原理是将这些语言的源代码(例如JavaScript)或源代码编译成中间格式(例如LLVM字节码、Class字节码)转换成可以被接受的中间表示(IntermediateRepresentation,IR)GraalVM通过解释器。例如,解释器被设计用来将LLVM输出的字节码转换为支持C和C++语言,这个过程称为“程序特化”(Specialized,也常被称为PartialEvaluation)。GraalVM提供了Truffle工具集来快速构建新语言的解释器,并用它构建了一个名为Sulong的高性能LLVM字节码解释器。从某种角度来说,GraalVM是真正意义上对应于物理计算机的高级语言虚拟机,因为它与物理硬件的指令集是一样的,只与机器特性有关,与机器特性无关某些高级语言的特性。.Graalvm的高级优化能力甲骨文实验室研究总监ThomasWuerthinger在接受采访时表示:“随着GraalVM1的发布,方式不再像Java虚拟机和MicrosoftCLR那样通过具有语言特性的字节码”。不以速度着称的语言运行环境,因为GraalVM本身可以自动优化输入的中间表示,也可以在运行时进行实时的编译优化,往往使用GraalVM实现比原生编译器更好的执行效率,例如,Graal.js优于Node.js,Graal.Python优于CPtyhon,TruffleRuby优于RubyMRI,FastR优于R语言,等等。Graalvm与Hotspot的比较GraalVM最初是在HotSpot的基础上诞生的,本质上可以作为一个完整的JavaSE8标准的Java虚拟机使用。它与标准版HotSpot的区别主要在于即时编译器,其执行效率和编译质量目前可与标准版HotSpot媲美。美国大学的Oracle实验室和研究机构对最新的即时编译技术的研究已经全部迁移到GraalVM上,其发展潜力令人期待。如果真有朝一日Java语言或者HotSpot虚拟机被取代,GraalVM似乎是今后最有希望的人选。这场革命很可能在Java用户没有明显感觉的情况下悄然来临。Java世界上所有的软件生态都没有丝毫改变,只是世界第一的位置悄然发生了变化。Graalvm即时编译器从JDK10开始,HotSpot中添加了一个新的即时编译器:Graal编译器。光看名字就可以联想到GraalVM。对于C1/C2即时编译器,对于需要长时间运行的应用程序,由于充分的预热,热点代码会被HotSpot的检测机制准确定位捕获,并编译成可运行的机器码直接由物理硬件执行。Java在类应用程序中的运行效率很大程度上取决于即时编译器输出的代码质量。HotSpot虚拟机中包含了两个即时编译器:客户端编译器(简称C1),编译时间长但输出代码优化质量更高(简称C2)通常他们会在分层编译机制下与解释器配合,构成HotSpot虚拟机的执行子系统。C2即时编译器,即Graal编译器,作为C2编译器的替代品被引入。C2的历史非常悠久,可以追溯到CliffClick读博士时的工作。Graal编译器,而Graal编译器本身就是用Java语言编写的。在实现时,它特意使用了与C2相同的称为“Sea-of-Nodes”的高级中间表示(HighIR)形式,从而更容易学习到C2的优点。Graal编译器比C2编译器晚了20年问世,具有极其丰富的后发优势。在保持输出类似质量编译代码的能力的同时,在开发效率和可扩展性方面明显优于C2编译器,这决定了C2编译器中优秀的代码优化技术可以很容易地移植到Graal编译器中,但是相反,Graal编译器中的有效优化在C2编译器中极难实现。在这种情况下,Graal的编译效果在短短几年内迅速赶上了C2,甚至在一些测试项目上逐渐超越了C2编译器。Graal可以做比C2更复杂的优化:“部分逃逸分析”(PartialEscapeAnalysis)比C2更容易使用“积极投机优化”(AggressiveSpeculativeOptimization)策略支持自定义预测假设,未来可期Graal编译器还很年轻,没有经过足够多的实践验证,所以还是贴着“实验状态”的标签,需要用开关参数激活。这让我想起了JDK1.3时代,那个时候HotSpot虚拟机刚刚诞生。场景也需要用开关激活,作为Classic虚拟机的替代品也是历史。Graal编译器的未来充满希望。作为最新的Java虚拟机代码执行引擎,它的不断完善将为HotSpot和GraalVM注入更快更强的驱动力。Compiletoanativeprogram编译成nativeprogram有一定的假设,比如:尽可能少的JNI调用,尽可能少用反射,类加载器隔离等。当这些复杂的功能不用的时候,很容易使用GraalVM提供了原生镜像将Jar编译成可执行程序。当然,即使程序使用了JNI和反射也没关系,我们可以通过一些配置文件告诉GraalVM单独处理这些信息,例如:通过参数-H:JNIConfigurationFiles告诉JNI相关的配置JSON文件告诉反射相关通过参数-H:ReflectionConfigurationFiles配置JSON文件稍微复杂一点,不过只要你有足够的耐心,理论上是可以编译成功的!但是,我们可以使用一些原生支持GraalVM原生镜像的框架,比如Quarkus。GraalVM的原生编译非常适合微服务和Serverless。当Java程序也可以被编译成原生可执行程序时(GraalVM已经支持Windows、MacOS和Linux上的原生程序),最重要的两个变化是:启动时间变短了。在使用“依赖注入”启动Java程序之前,可能需要2秒以上才能启动。如果Java程序要长时间运行,启动时间稍慢一点还好,但是对于Serverless应用来说,这就变成了冷启动(coldstart),影响比较大。程序运行的内存需求变小了。在启动Java程序之前,如果控制的好(堆设置比较小),需要100M以上的内存,但是编译成native程序后,只需要4M内存就足够了。这样同一台机器可以启动很多进程,适合简单的微服务。这里是小编的另一篇文章:《看完这份 JVM 高级笔记,彻底掌握Java 虚拟机,面试再也不用“虚”了》感兴趣的可以点击观看
