JEP 148:小型虚拟机
概述
支持创建一个不大于 3 MB 的小型虚拟机。
目标
进行必要的修改,以便我们可以选择性地构建一个不大于 3MB 的小型虚拟机。(作为参考,客户端和服务端的虚拟机目前分别约为 6MB 和 9MB。)
这将通过允许在构建时排除某些特性,并在可能的情况下优化 C++ 编译代码的空间来实现。对于小型虚拟机,性能下降最多可接受 5%。对于非小型构建,必须没有任何性能下降。
非目标
没有计划保留全部功能。没有计划在运行时使功能可选。
成功指标
libjvm.so
的大小小于 3 MB,性能下降不超过 5%。
动机
小型设备对静态和动态内存占用有非常严格的要求。为了让 Java 在此类设备上良好运行,我们需要减少 JRE 的整体静态和动态内存占用。
描述
在实现 Java Kernel 时,曾进行过一项缩减 libjvm.so
大小的早期工作。Kernel VM 移除了一些较大的组件,例如额外的垃圾收集器、C2 JIT 编译器以及大部分 JVMTI 功能。
内核虚拟机(VM)一直没有得到维护,并且从未在 Linux 上实现。该项目的第一步是为 Linux 重新激活与该虚拟机等效的功能。
在内核虚拟机(VM)中,修改了 makefile 和相关构建文件,以排除实现必要功能所不需要的文件。我们正在采取一种略有不同的方法,计划通过条件语句修改源文件,而不是修改构建文件。现有的条件符号 KERNEL
将变为 MINIMAL_JVM
,而内核虚拟机排除的源文件将被 #ifndef MINIMAL_JVM
包围。此外,为了更精细地控制最小虚拟机中包含的内容,将定义类似 INCLUDE_\<something>
的符号,以包含否则会被排除的功能。对于最小虚拟机,这些符号将不会被定义。
一旦最小化虚拟机(VM)在必要平台上稳定运行,其他非必要功能将变为可选。我们认为实现这一目标的主要方法是:从最小化虚拟机中移除 JVMTI、java.lang.instrument
支持(在 sun.instrument
中实现)、sun.management
以及监控功能(属于 PerfDataManager
的一部分)。
大部分的 JVMTI 已经从内核虚拟机中移除。剩余的 JVMTI 代码将会通过 #ifdef
进行编译时条件化处理。
移除功能的公共 API 可能需要进行修改,以便在未实现时抛出适当的异常。
该项目的另一部分包括找到那些可以在不牺牲性能的情况下进行空间优化的文件。这涉及到修改构建过程,使得可以方便地指定哪些文件需要进行空间优化。对于大多数文件,我们将使用 gcc
的 -Os
选项来进行空间优化。在某些平台上可能还有其他减少空间的选项。如果性能有显著下降,我们将使用性能剖析(profiling)来确定哪些文件可以使用 -O3
编译以加速。这可能涉及将函数移动到不同的文件中,以便只有那些对性能至关重要的函数才会以此方式编译。
测试
如果底层实现代码缺失,API 必须表现得当。这些更改必须通过 Java SE 8 TCK(技术兼容性套件)测试。需要进行性能测试以衡量缩减工作带来的影响。
风险与假设
可能存在我们不知道的对已移除功能的虚拟机依赖关系。
有可能,但不太可能,没有足够的可选功能可以删除以达到我们的目标。
假定 JDK 8 不会显著增加 libjvm.so
的大小。
影响
- 其他 JDK 组件:某些工具可能依赖缺失的代码。
- 兼容性:在最小化二进制文件中将不支持 JVMTI。
- 性能/可扩展性:当构建此配置时,可能会测量到对性能的一些轻微影响。
- 文档:需要记录二进制文件中不支持的内容,以及用户或工具尝试访问缺失功能时会发生什么。
- TCK(技术兼容性套件):可能需要一些 TCK 的更改,以支持因移除特性而产生的 API 变化。
- 质量保证(QA):需要进行额外的测试,以确保小型二进制文件正常工作。可能需要更新测试,以考虑可选功能。
- 用户体验:用户可能期望所有虚拟机都具备完整功能,但小型虚拟机中会省略某些功能。