- 2018年4月,Oracle Labs新公开一项黑科技:Graal VM。它的口号是“Run Programs Faster Anywhere”
- 被官方称为“Universal VM”和“Poly glot VM”,在HotSopt虚拟机基础上增强而成的跨语言全栈虚拟机
- 可以作为“任何语言”的运行平台使用(包括Java、Scala、Groovy、Kotlin等基于Java虚拟机的,甚至C、C++、Rust等基于LLVM的语言,另外JavaScript、Ruby、Python和R语言等也支持)
- Graal VM可以无额外开销地
混合使用这些编程语言
,支持不同语言中混用对方的接口和对象,也能支持这些语言使用已经编写好的本地库文件。
- 基本工作原理是,将这些语言的源代码(例如JavaScript)或编译后的中间格式(例如LLVM字节码)通过解释器转换为能被Graal VM接受的中间表示,这个过程称为序特化。Graal VM提供了Truffle工具集来快速构建面向一种新语言的解释器,并用它构建了一个称为Sulong的高性能LLVM字节码解释器
————所以,如果Graal VM成功,成为世界主流,那么XXX程序员还会存在么?更多的,大家会关注某一业务方向,毕竟如果可以任意使用各种语言的优势组合开发项目,那么知道怎么组合各种语言为更优的人,才是真正的高手与市场所需。
————是否需要特定学习多门编程语言呢?我觉得大可不必,学好一门编程语言后,其它语言看看文档,用着用着也就会了。关键是如何发挥各种语言的长处,如何扬长避短。
————另外,只要掌握了Graal VM的Truffle工具,我们大可只关注如何设计编程语言语法可以更有效开发,如何合理的通过工具,将编程语言转换为Graal VM可以识别的字节码。
————未来,可能写一个项目就可以自己规定一个编程语言,最终发展成Unity3d和虚幻游戏引擎内样,一种特定场景下,通用的游戏引擎。
————那么这种情况可能发生在多久以后?5到10年后吧,看硬件产品和用户需求了,如果你现在开始持续学习,正好到那时是分第一杯羹的人。反正闲着也是闲着,没事看两篇文档就好完事了。
- 目前JDK8的编译器有两个,编译耗时低,输出代码优化程度也低的C1(简称)客户端编译器。还有一个编译耗时长,但是输出代码质量更高的C2(简称)服务端编译器。通常在分层编译机制下,与解释器互相配合来构成HotSpot虚拟机执行子系统
- JDK10起,HotSpot加入了Graal编译器,以C2替代者的身份出现。C2由C++编写,虽然现在依然效果拔群,但是已经复杂度作者都不愿意维护了。而Graal本身就是Java编写,很好的借鉴了C2的优点,保证输出质量和C2相差不多的前提下,开发效率和扩展性都更上一层楼
- C2中优秀的代码优化技术,可以轻松移植到Graal,但是反过来C2却异常艰难,Graal编译效果短短几年就追平C2,甚至有些方面逐渐反超C2
- 可以比C2做更加复杂的优化,例如“部分逃逸分析”,也更容易使用激进预测性优化的策略,支持自定义的预测性假设
- Craal依然是发展中编译器,需要施一公开关参数去激活(用-XX:+UnlockExperimentalVMOptions-XX:+UseJVMCICompiler参数来启用Graal编译器)
Substrate VM解决Graal VM的重量级负担,以及JDK新版功能清单中的解决措施 |
- 我们知道目前Java有第一次运行很慢(重量高)的毛病,在目前微服务应用架构下,有了高可用服务集群,Java的启动时长,需要预热(找到热点代码进行即时编译),相悖与这种架构场景
- 在无服务架构中,更是严重。比起服务,函数的规模更小,执行时间更短,现在非常火的无服务运行环境AWS Lambda所允许最长运行时间仅仅15分钟
- Java自然会跟上潮流,最新的JDK版本功能清单中,陆续推出跨进程、面向用户程序的类型信息共享、无操作垃圾回收器等改善措施。而还有一个更彻底的解决方案,逐步对提前编译(AOT)提供支持。
- 面向用户程序的类型信息共享:AppCDS,运行把加载解析后的类型信息缓存,提高下次启动速度,原本CDS只支持Java标准库,JDK10时,AppCDS开始支持用户程序代码
- 无操作垃圾回收器:Epsilon,只做内存分配而不做回收的收集器,对于运行完就退出的应用十分合适。
- 提前编译:好处是Java虚拟机加载这些已经预编译成二进制库的东西,能够直接调用,无需等待即时编译器在运行时将其编译成二进制机器码。可以减少即时编译带来的预热时间。但是破坏了“一次编写,到处运行”的承诺,必须为每个不同的硬件、操作系统去编译对应发行包,显著降低Java链接过程的动态性,必须要求加载的代码再编译器全部已知,不能运行期才确定,否则只能舍弃已经提前编译好的版本,回退到即时编译执行
- JDK 9 提供jaotc命令进行提前编译,但不是生成本地代码完全脱离Java虚拟机,只是代替即时编译,编译一部分代码,仍然需要运行在HotSpot之上
- Substrate VM出现,满足了人们对Java提前编译的期待。在Graal VM0.2,0版本出现的极小型运行时环境,包括了独立的异常处理、同步调度、线程管理、内存管理(垃圾收集)和JNI访问等组件,目标是代替HotSpot用来支持提前编译后的程序执行。
- 还包括一个本地镜像构造器(Native Image Generator),为用户程序建立Substrate VM的本地运行时镜像,采用指针分析(Points-To Analysis)技术,从用户提供程序入口出发,搜索所有可达代码,搜索时,还会执行初始化代码,最终生成可执行文件时,将已初始化的堆,存入一个堆快照中,这让Substrate VM可以直接从目标程序开始运行,无须重复进行Java虚拟机的初始化过程。
- 原理上决定,Substrate VM必须要求目标程序完全封闭,不能动态加载其它编译器不可知的代码和类库。遵循这些,Substrate VM才能探索整个编译空间,并通过静态分析推算出所有虚方法调用的目标方法
- 可以显著降低内存占用及启动时间,补全了Graal VM在任何地方更快运行任何代码的最后一块拼图,让Graal VM支持其它语言时不会有重量级的运行负担。
Substrate VM的轻量级特性,是它十分适合嵌入其他系统,Oracle自家数据库已经开始使用这种方式支持用不同语言代替PL/SQL来编写存储过程。
- HotSpot定位是面向各种不同应用场景的全能Java虚拟机。开发团队正在持续重构HotSpot架构,让它具有模块化能力和足够的开放性
- 模块化是HotSpot的弱项,IBM的J9做的一直非常好,面向Java ME的J9虚拟机与面向Java EE的J9虚拟机,完全可以由同一套代码库编译出来,只有编译时选择的模块配置有所差别
- 现在,HotSpot也有了J9类似的能力,能够实现功能特性的组合拆分,反映到源码不光是条件编译,关键是接口与实现的分离
- JDK9时期,HotSpot开放了Java语言级别的编译器接口JVMCI,使Java虚拟机外部增加、替换即时编译器成为可能
- JDK10,重构了Java虚拟机垃圾回收器接口,统一内部各款垃圾回收器的公共行为,有了这个接口,未来某版本CMS回收器退役成为可能,也发生JDK12中Shenandoah这样有Oracle以外的厂商领导开发的垃圾回收器进入HotSpot中的事情
- 虽然HotSpot代码越来越多,越来越复杂,但架构依然能打,拥有了越来越多的开放性和扩展性,能够联动外部功能,应对各种场景,再统治个三五年不成问题。
- 这个对于改进点来说,也不太重要,毕竟JavaScript内样的语法都火了,火到现在,而且我还挺喜欢JavaScript的。但是像C#那样语法优雅的语法糖,还是让程序员很有幸福感的。
- 除语法糖以外,语言的功能也在持续改进之中
- Project Loom:准备提供一套与目前Thread类API非常接近的Fiber实现,提供了更加轻量级的、由软件自身进行调度的用户线程
- Project Valhalla:提供值类型和基本类型的泛型支持,并提供明确的不可变类型和非引用类型的声明,基本类型的范型支持是指在泛型中引用基本数据类型不需要自动装箱和拆箱,避免性能损耗
- Project Panama:目的是消弭Java虚拟机与本地代码之间的界线,提供更好的方式让Java代码与本地代码进行调用和传输数据
本文是我的JVM的学习笔记,可以当做复习和参考资料,如果想要真正学会,还是要去看书哦!我学习JVM的书籍如下 |
- 深入理解Java虚拟机:JVM高级特性与最佳实践(看完爆杀面试官)