11.3 提前编译器

11.3 提前编译器

提前编译在Java技术体系中并不是新事物。1996年JDK 1.0发布,Java有了正式的运行环境,第一个可以使用外挂即时编译器的Java版本是1996年7月发布的JDK 1.0.2,而Java提前编译器的诞生并没有比这晚多少。仅几个月后,IBM公司就推出了第一款用于Java语言的提前编译器(IBM High Performance Compiler for Java)。在1998年,GNU组织公布了著名的GCC家族(GNU Compiler Collection)的新成员GNU Compiler for Java(GCJ,2018年从GCC家族中除名),这也是一款Java的提前编译器^1,而且曾经被广泛应用。在OpenJDK流行起来之前,各种Linux发行版带的Java实现通常就是GCJ。

但是提前编译很快又在Java世界里沉寂了下来,因为当时Java的一个核心优势是平台中立性,其宣传口号是“一次编译,到处运行”,这与平台相关的提前编译在理念上就是直接冲突的。GCJ出现之后在长达15年的时间里,提前编译这条故事线上基本就再没有什么大的新闻和进展了。类似的状况一直持续至2013年,直到在Android的世界里,剑走偏锋使用提前编译的ART(Android Runtime)横空出世。ART一诞生马上就把使用即时编译的Dalvik虚拟机按在地上使劲蹂躏,仅经过Android 4.4一个版本的短暂交锋之后,ART就迅速终结了Dalvik的性命[^2],把它从Android系统里扫地出门。

尽管Android并不能直接等同于Java,但两者毕竟有着深厚渊源,提前编译在Android上的革命与崛起也震撼到了Java世界。在某些领域、某些人眼里,只要能获得更好的执行性能,什么平台中立性、 字节膨胀[^3]、动态扩展[^4],一切皆可舍弃,唯一的问题就只有“提前编译真的会是获得更高性能的银弹吗?”

[^2]: ART干掉Dalvik之后,到Android 7.0时其内部也加入了解释执行和即时编译,这是后话。
[^3]: 指提前编译的本地二进制码的体积会明显大于字节码的体积。
[^4]: 指提前编译通常要求程序是封闭的,不能在外部动态加载新的字节码。