实时系统和垃圾收集
实时(RT)应用程序开发与通用应用程序开发的差异在于前者对部分运行时行为强加了时间限制。此类限制通常是对应用程序的某些部分实施的,比如中断处理程序,其响应中断的代码必须在给定的时间范围内完成工作。对于硬 RT 系统,比如心脏监测器或国防系统,如果这类系统的运行超出时限,可以看作是整个系统的灾难性失败。而对于软 RT 系统,超出时限可能会有些不利影响 —— 比如 GUI 不能显示其监控流的所有结果 —— 但是不会导致系统失败。
在 Java 应用程序中,Java 虚拟机(JVM)负责优化运行时行为、管理对象堆以及接合操作系统和硬件。虽然语言和平台之间的这个管理层简化了软件开发,但同时也给程序带来了一定数量的开销。GC 就是一个这样的例子,它通常会导致应用程序中的不确定性暂停。暂停的频率和时长都不可预测,使得 Java 语言在传统上并不适合开发 RT 应用程序。一些基于 Java 实时规范(RTSJ)的现有解决方案使开发人员能够避开 Java 技术的不确定性方面,但是需要对现有的编程模型做些更改。
Metronome 是一种确定性的垃圾收集器,为标准的 Java 应用程序提供有限制的低暂停时间和指定的应用程序利用率。有限制的暂停时间的减少源于收集方法的增加和细致的工程决断,包括对 VM 的基本更改。利用率是指应用程序所能够运行的特定时间窗中的时间百分比,剩余时间则用于 GC。Metronome 让用户能够指定应用程序的利用率级别。通过与 RTSJ 结合使用,Metronome 使开发人员能够在时间窗很小的情况下构建具有确定的低暂停时间和无暂停的软件。本文解释了 RT 应用程序的传统 GC 的限制,详述了 Metronome 的方法,并且为使用 Metronome 开发硬 RT 应用程序提供了一些工具和指导。
传统 GC
传统 GC 实现使用 stop-the-world (STW) 方法来恢复堆内存。应用程序一直运行,直至耗尽堆的可用内存,此时 GC 停止所有的应用程序代码、执行垃圾收集,然后让应用程序继续运行。
图 1 演示了用于 GC 活动的传统的 STW 暂停,这些暂停在频率和持续时间方面通常都不可预测。传统的 GC 是不确定的,因为恢复内存所需执行工作的数量取决于应用程序所使用对象的总的数量和大小、这些对象之间的相互连接,以及为释放足够的堆内存以满足未来分配所需完成的工作的多少。
图 1. 传统 GC 暂停