没有虚拟机的 Java
某些 Java 语言的特性,使得 Graal VM 编译本地镜像的过程变得极为艰难。譬如常见的反射,除非使用安全管理器去专门进行认证许可,否则反射机制具有在运行期动态调用几乎所有 API 接口的能力,且具体会调用哪些接口,在程序不会真正运行起来的编译期是无法获知的。反射显然是 Java 不能放弃不能妥协的重要特性,为此,只能由程序的开发者明确地告知 Graal VM 有哪些代码可能被反射调用(通过 JSON 配置文件的形式),Graal VM 才能在编译本地程序时将它们囊括进来。
这是一种可操作性极其低下却又无可奈何的解决方案,即使开发者接受不厌其烦地列举出自己代码中所用到的反射 API,但他们又如何能保证程序所引用的其他类库的反射行为都已全部被获知,其中没有任何遗漏?与此类似的还有另外一些语言特性,如动态代理等。另外,一切非代码性质的资源,如最典型的配置文件等,也都必须明确加入配置中才能被 Graal VM 编译打包。这导致了如果没有专门的工具去协助,使用 Graal VM 编译 Java 的遗留系统即使理论可行,实际操作也将是极度的繁琐。
……
以上,是 Graal VM 在 Java 语言中面临的部分困难,在整个 Java 的生态系统中,数量庞大的第三方库才是真正最棘手的难题。可以预料,这些第三方库一旦脱离了 Java 虚拟机,在原生环境中肯定会暴露出无数千奇百怪的异常行为。Graal VM 团队对此的态度非常务实,并没有直接硬啃。要建设可持续、可维护的 Graal VM,就不能为了兼容现有 JVM 生态,做出过多的会影响性能、优化空间和未来拓展的妥协牺牲,为此,应该也只能反过来由 Java 生态去适应 Graal VM,这是 Graal VM 团队明确传递出对第三方库的态度:
Graal VM native support needs to be sustainable and maintainable, that’s why we do not want to maintain fragile pathches for the whole JVM ecosystem.
The ecosystem of libraries needs to support it natively.
—— Sébastien Deleuze,