【JVM深层系列】「云原生时代的Java虚拟机」针对于GraalVM的技术知识脉络的重塑和探究

简介: 【JVM深层系列】「云原生时代的Java虚拟机」针对于GraalVM的技术知识脉络的重塑和探究

GraalVM 背景


新、旧编程语言的兴起躁动,说明必然有其需求动力所在,譬如互联网之于JavaScript、人工智能之于Python,微服务风潮之于Golang等等。大家都清楚不太可能有哪门语言能在每一个领域都尽占优势,Java已是距离这个目标最接近的选项,但若“天下第一”还要百尺竿头更进一步的话,似乎就只能忘掉Java语言本身,踏入无招胜有招的境界。


  • 更进一步提升JVM上运行的程序的性能
  • 通过预编译(ahead-of-time)编译Java程序为原生可执行程序
  • 多种编程语言混编在一个程序中(polyglot)
  • 类似于LLVM,GraalVM也提供了方便的机制方便开发新的编程语言


官方网站在: www.graalvm.org/




当前痛点


在云原生时代,Java程序是有很大的劣势的,为什么这么说呢?一般的Java应用程序都要几十兆的内存,启动也不不快。


最流行的SpringBoot/SpringCloud微服务框架为例,启动一个已经优化好,很多bean需要lazy load的application至少需要3-4秒时间,内存需要几百兆,业务逻辑稍微复杂一点点,没有1G以上的内存是很难满足业务的需要呢?


那么在云原生时代,一个充满黑科技的JVM介绍给大家,它能帮助我们让Java程序的启动速度加快100倍,内存只需要原来的五分之一,甚至更少。



Graalvm的介绍


  • GraalVM是2018年Oracle开发的下一代JVM实现,被官方称为“Universal VM”和“Polyglot VM”,这是一个在HotSpot虚拟机基础上增强而成的跨语言全栈虚拟机,可以作为“任何语言”的运行平台使用。


  • 这里“任何语言”包括了Java、Scala、Groovy、Kotlin等基于Java虚拟机之上的语言,还包括了C、C++、Rust等基于LLVM的语言,同时支持其他像JavaScript、Ruby、Python和R语言等等。

image.png

GraalVM可以无额外开销地混合使用这些编程语言,支持不同语言中混用对方的接口和对 象,也能够支持这些语言使用已经编写好的本地库文件。


它的口号“Run Programs Faster Anywhere”就能感觉到一颗蓬勃的野心



Graalvm性能的对比


GraalVM的性能真的不错。以JDK 8为例


  • OpenJDK
  • Oracle JDK


其中OpenJDK是通过“GPL v2 with CE”协议开源的,可以免费商用的。


之前在用Apache Spark测试性能时, 对比一下两者性能, 稍微数据量大点的查询,会发现Oracle JDK一般都会比OpenJDK快30%以上。


  • 而GraalVM分为社区版和商业版,其中GraalVM的社区版也是采用了和OpenJDK一样的“GPL v2 with CE”协议开源的。
  • 对于GraalVM的社区版,非常惊喜的发现其比Oracle JDK也会快10%以上。
  • 没有试过GraalVM的商业版, 官方报道,其商业版比社区版提升的性能更多



Graalvm主要特性


  • 高性能的现代Java
  • 占用资源少,启动速度快
  • JavaScript,Java, Ruby以及R混合编程
  • 在JVM上运行原生语言
  • 跨语言工具
  • JVM应用扩展
  • 原生应用扩展
  • 本地Java库
  • 数据库支持多语言
  • 创建自己的语言



Graalvm工作原理


GraalVM的基本工作原理是将这些语言的源代码(例如,JavaScript)或源代码编译后的中间格式(例如,LLVM字节码、Class字节码)通过解释器转换为能被GraalVM接受的中间表示(Intermediate Representation,IR),譬如设计一个解释器专门对LLVM输出的字节码进行转换来支持C和C++语言,这个过程称为“程序特化”(Specialized,也常称为Partial Evaluation)。


GraalVM提供了Truffle工具集来快速构建面向一种新语言的解释器,并用它构建了一个称为Sulong的高性能LLVM字节码解释器。


从某个角度来看,GraalVM才是真正意义上与物理计算机相对应的高级语言虚拟机,因为它与物理硬件的指令集一样,做到了只与机器特性相关而不与某种高级语言特性相关。



Graalvm的高等优化能力


Oracle Labs的研究总监Thomas Wuerthinger在接受采访时谈到:“随着GraalVM1.0的发布,已经证明了拥有高性能的多语言虚拟机是可能的,并且实现这个目标的最佳方式不是通过类似Java虚拟机和微软CLR那样带有语言特性的字节码”。


本来就不以速度见长的语言运行环境,由于GraalVM本身能够对输入的中间表示进行自动优化,在运行时还能进行即时编译优化,往往使用GraalVM实现能够获得比原生编译器更优秀的执行效率,譬如Graal.js要优于Node.js、Graal.Python要优于CPtyhon,TruffleRuby要优于Ruby MRI,FastR要优于R语言等等。


Graalvm与Hotspot的对比


GraalVM本来就是在HotSpot基础上诞生的,天生就可作为一套完整的符合Java SE8标准Java虚拟机来使用。


它和标准的HotSpot差异主要在即时编译器上,其执行效率、编译质量目前与标准版的HotSpot相比也是互有胜负。


Oracle Labs和美国大学里面的研究院所做的最新即时编译技术的研究全部都迁移至基于GraalVM之上进行了,其发展潜力令人期待。


如果Java语言或者HotSpot虚拟机真的有被取代的一天,那从现在看来GraalVM是希望最大的一个候选项,这场革命很可能会在Java使用者没有明显感觉的情况下悄然而来,Java世界所有的软件生态都没有发生丝毫变化,但天下第一的位置已经悄然更迭。



Graalvm即时编译器


自JDK 10起,HotSpot中又加入了一个全新的即时编译器:Graal编译器,看名字就可以联想到它是来自于Graal VM。



C1/C2即时编译器


对需要长时间运行的应用来说,由于经过充分预热,热点代码会被HotSpot的探测机制准确定位捕获,并将其编译为物理硬件可直接执行的机器码,在这类应用中Java的运行效率很大程度上是取决于即时编译器所输出的代码质量。


HotSpot虚拟机中包含有两个即时编译器:


  • 编译时间较短但输出代码优化程度较低的客户端编译器(简称为C1)
  • 编译耗时长但输出代码优化质量也更高的服务端编译器(简称为C2)


通常它们会在分层编译机制下与解释器互相配合来共同构成HotSpot虚拟机的执行子系统的。



C2即时编译器


Graal编译器是作为C2编译器替代者的角色登场的。C2的历史已经非常长了,可以追溯到Cliff Click大神读博士期间的作品,这个由C++写成的编译器尽管目前依然效果拔群,但已经复杂到连Cliff Click本人都不愿意继续维护的程度。



Graal编译器


而Graal编译器本身就是由Java语言写成,实现时又刻意与C2采用了同一种名为“Sea-of-Nodes”的高级中间表示(High IR)形式,使其能够更容易借鉴C2的优点。


Graal编译器比C2编译器晚了足足二十年面世,有着极其充沛的后发优势,在保持能输出相近质量的编译代码的同时,开发效率和扩展性上都要显著优于C2编译器,这决定了C2编译器中优秀的代码优化技术可以轻易地移植到Graal编译器上,但是反过来Graal编译器中行之有效的优化在C2编译器里实现起来则异常艰难。


这种情况下,Graal的编译效果短短几年间迅速追平了C2,甚至某些测试项中开始逐渐反超C2编译器。


Graal能够做比C2更加复杂的优化:


  • “部分逃逸分析”(Partial Escape Analysis)
  • 比C2更容易使用“激进预测性优化”(Aggressive Speculative Optimization)的策略
  • 支持自定义的预测性假设



未来可期


Graal编译器尚且年幼,还未经过足够多的实践验证,所以仍然带着“实验状态”的标签,需要用开关参数去激活,这让笔者不禁联想起JDK 1.3时代,HotSpot虚拟机刚刚横空出世时的场景,同样也是需要用开关激活,也是作为Classic虚拟机的替代品的一段历史。


Graal编译器未来的前途可期,作为Java虚拟机执行代码的最新引擎,它的持续改进,会同时为HotSpot与Graal VM注入更快更强的驱动力。



编译为原生执行程序


编译为原生程序有一定的假设条件,比如:


  • 尽量少的JNI调用
  • 尽量少的使用反射
  • 尽量少的class loader隔离等


当没有用这些复杂功能的时候,很容易可以使用GraalVM提供的 native image 编译Jar为可执行程序。

当然即使当程序使用了 JNI、反射时,也没关系,我们可以使用一些配置文件告诉GraalVM单独处理这些信息,比如:


  • 通过参数 -H:JNIConfigurationFiles 告诉JNI相关配置JSON文件
  • 通过参数 -H:ReflectionConfigurationFiles 告诉反射相关配置JSON文件


稍微会复杂一些,但是只要有足够的耐心,理论上也是可以编译成功的!

不过我们可以使用一些原生支持GraalVM native image的框架, 比如:Quarkus。



GraalVM的原生编译非常适合微服务和 Serverless


当可以把Java程序也编译为原生的可执行程序后 (目前GraalVM已经支持编译为Windows, MacOS, Linux上的原生程序),最主要的两个变化:


  • 启动时间变短了,之前启动一个有“依赖注入”的Java程序,可能启动时间要2秒以上。如果Java程序是要长期运行的,那启动时间稍慢一点是没问题的,但是对于 Serverless 应用,这就变为冷启动(cold start)了,影响比较大。


  • 程序运行的内存需求变小了,之前启动一个Java程序,控制的好的话(heap设置的比较小),也要100M以上的内存,但是编译为原生程序后,只需要4M内存就可以了。 这样同样的一台机器就可以启动非常多的进程,适合简单的微服务。




参考资料





相关文章
|
8天前
|
Cloud Native 安全 物联网
云原生技术在现代软件开发中的应用与挑战####
云原生,这一词汇如同一股强劲的科技风暴,席卷了整个信息技术领域,它不仅重塑了软件的开发模式,还引领了一场关于效率、可扩展性和弹性的深刻变革。本文旨在深入探讨云原生技术的核心概念,分析其在现代软件开发中的广泛应用,并直面伴随其发展而来的挑战,为读者勾勒出一幅既充满机遇又不乏考验的云原生技术图景。 ####
|
3天前
|
Cloud Native 前端开发 JavaScript
前端开发者必看:不懂云原生你就OUT了!揭秘如何用云原生技术提升项目部署与全栈能力
【10月更文挑战第23天】随着云计算的发展,云原生逐渐成为技术热点。前端开发者了解云原生有助于提升部署与运维效率、实现微服务化、掌握全栈开发能力和利用丰富技术生态。本文通过示例代码介绍云原生在前端项目中的应用,帮助开发者更好地理解其重要性。
17 0
|
5天前
|
Kubernetes Cloud Native 持续交付
云端新纪元:云原生技术重塑IT架构####
【10月更文挑战第20天】 本文深入探讨了云原生技术的兴起背景、核心理念、关键技术组件以及它如何引领现代IT架构迈向更高效、灵活与可扩展的新阶段。通过剖析Kubernetes、微服务、Docker等核心技术,本文揭示了云原生架构如何优化资源利用、加速应用开发与部署流程,并促进企业数字化转型的深度实践。 ####
|
2天前
|
SQL 监控 Java
技术前沿:Java连接池技术的最新发展与应用
本文探讨了Java连接池技术的最新发展与应用,包括高性能与低延迟、智能化管理和监控、扩展性与兼容性等方面。同时,结合最佳实践,介绍了如何选择合适的连接池库、合理配置参数、使用监控工具及优化数据库操作,为开发者提供了一份详尽的技术指南。
17 7
|
4天前
|
移动开发 前端开发 Java
过时的Java技术盘点:避免在这些领域浪费时间
【10月更文挑战第14天】 在快速发展的Java生态系统中,新技术层出不穷,而一些旧技术则逐渐被淘汰。对于Java开发者来说,了解哪些技术已经过时是至关重要的,这可以帮助他们避免在这些领域浪费时间,并将精力集中在更有前景的技术上。本文将盘点一些已经或即将被淘汰的Java技术,为开发者提供指导。
29 7
|
2天前
|
Java 数据库连接 数据库
优化之路:Java连接池技术助力数据库性能飞跃
在Java应用开发中,数据库操作常成为性能瓶颈。频繁的数据库连接建立和断开增加了系统开销,导致性能下降。本文通过问题解答形式,深入探讨Java连接池技术如何通过复用数据库连接,显著减少连接开销,提升系统性能。文章详细介绍了连接池的优势、选择标准、使用方法及优化策略,帮助开发者实现数据库性能的飞跃。
14 4
|
2天前
|
SQL Java 数据库连接
打破瓶颈:利用Java连接池技术提升数据库访问效率
在Java应用中,数据库访问常成为性能瓶颈。连接池技术通过预建立并复用数据库连接,避免了频繁的连接建立和断开,显著提升了数据库访问效率。常见的连接池库包括HikariCP、C3P0和DBCP,它们提供了丰富的配置选项和强大的功能,帮助优化应用性能。
15 2
|
2天前
|
敏捷开发 Cloud Native 持续交付
云原生技术在现代企业中的应用与实践
【10月更文挑战第23天】本文将深入探讨云原生技术在现代企业中的广泛应用,并结合具体案例分析其对企业数字化转型的推动作用。我们将从云原生技术的基本原理出发,逐步揭示其在提高业务敏捷性、降低成本和增强系统可靠性方面的优势。同时,文章还将分享一系列成功实施云原生技术的企业案例,为读者提供实践中的参考和启示。最后,我们将讨论云原生技术面临的挑战及未来的发展趋势,为企业在这一领域的进一步探索提供指导。
|
4天前
|
Kubernetes Cloud Native 开发者
云原生技术入门:Kubernetes和Docker的协作之旅
【10月更文挑战第22天】在数字化转型的浪潮中,云原生技术成为推动企业创新的重要力量。本文旨在通过浅显易懂的语言,引领读者步入云原生的世界,着重介绍Kubernetes和Docker如何携手打造弹性、可扩展的云环境。我们将从基础概念入手,逐步深入到它们在实际场景中的应用,以及如何简化部署和管理过程。文章不仅为初学者提供入门指南,还为有一定基础的开发者提供实践参考,共同探索云原生技术的无限可能。
16 3
|
3天前
|
Cloud Native 持续交付 云计算
云原生技术深度探索:构建现代化应用的基石####
【10月更文挑战第21天】 本文将深入探讨云原生技术的核心概念、关键技术及其在现代软件开发中的应用。我们将从容器化、微服务架构、持续集成/持续部署(CI/CD)、无服务器架构等关键方面展开,揭示这些技术如何共同作用,帮助企业实现高效、弹性且易于维护的应用部署与管理。通过实例分析,展现云原生技术在实际项目中的显著优势,为读者提供一套全面理解并应用云原生技术的指南。 ####
16 2