1.5 展望Java技术的未来 1.5.4 灵活的胖子
HotSpot的定位是面向各种不同应用场景的全功能Java虚拟机[^1],这是一个极高的要求,仿佛是让 一个胖子能拥有敏捷的身手一样的矛盾。如果是持续跟踪近几年OpenJDK的代码变化的人,相信都感 觉到了HotSpot开发团队正在持续地重构着HotSpot的架构,让它具有模块化的能力和足够的开放性。 模块化[^2]方面原本是HotSpot的弱项,监控、执行、编译、内存管理等多个子系统的代码相互纠缠。 而IBM的J9就一直做得就非常好,面向Java ME的J9虚拟机与面向Java EE的J9虚拟机可以是完全由同一 套代码库编译出来的产品,只有编译时选择的模块配置有所差别。
现在,HotSpot虚拟机也有了与J9类似的能力,能够在编译时指定一系列特性开关,让编译输出的 HotSpot虚拟机可以裁剪成不同的功能,譬如支持哪些编译器,支持哪些收集器,是否支持JFR、 AOT、CDS、NMT等都可以选择。能够实现这些功能特性的组合拆分,反映到源代码不仅仅是条件编 译,更关键的是接口与实现的分离。
早期(JDK 1.4时代及之前)的HotSpot虚拟机为了提供监控、调试等不会在《Java虚拟机规范》 中约定的内部功能和数据,就曾开放过Java虚拟机信息监控接口(Java Virtual Machine Profiler Interface,JVMPI)与Java虚拟机调试接口(Java Virtual Machine Debug Interface,JVMDI)供运维和性 能监控、IDE等外部工具使用。到了JDK 5时期,又抽象出了层次更高的Java虚拟机工具接口(Java Virtual Machine Tool Interface,JVMTI)来为所有Java虚拟机相关的工具提供本地编程接口集合,到 JDK 6时JVMTI就完全整合代替了JVMPI和JVMDI的作用。
在JDK 9时期,HotSpot虚拟机开放了Java语言级别的编译器接口[^3](Java Virtual Machine Compiler Interface,JVMCI),使得在Java虚拟机外部增加、替换即时编译器成为可能,这个改进实现起来并不 费劲,但比起之前JVMPI、JVMDI和JVMTI却是更深层次的开放,它为不侵入HotSpot代码而增加或 修改HotSpot虚拟机的固有功能逻辑提供了可行性。Graal编译器就是通过这个接口植入到HotSpot之 中。
到了JDK 10,HotSpot又重构了Java虚拟机的垃圾收集器接口[^4](Java Virtual Machine Compiler Interface),统一了其内部各款垃圾收集器的公共行为。有了这个接口,才可能存在日后(今天尚未) 某个版本中的CMS收集器退役,和JDK 12中Shenandoah这样由Oracle以外其他厂商领导开发的垃圾收 集器进入HotSpot中的事情。如果未来这个接口完全开放的话,甚至有可能会出现其他独立于HotSpot 的垃圾收集器实现。
经过一系列的重构与开放,HotSpot虚拟机逐渐从时间的侵蚀中挣脱出来,虽然代码复杂度还在增 长,体积仍在变大,但其架构并未老朽,而是拥有了越来越多的开放性和扩展性,使得HotSpot成为一 个能够联动外部功能,能够应对各种场景,能够学会十八般武艺的身手灵活敏捷的“胖子”。
[^1]: 定位J9做到了,HotSpot实际上并未做到,譬如在Java ME中的虚拟机就不是HotSpot,而是CDC-HI/CLDC-HI。
[^2]: 这里指虚拟机本身的模块化,与Jigsaw无关。
[^3]: 并不是指内部代码上统一C1、C2的编译器接口,而是特指会开放给外部的、使用Java语言实现的编 译器接口。
[^4]: 这个接口目前只在HotSpot内部使用,并未对外开放,所以也就没有JVMGI的提法。