本文档针对JDK8 HotSpot虚拟机,纯人工翻译,在力求准确表达官方文档原义的基础之上,会适当意译,不至于让译文显得太晦涩难懂。
小至桌面applet大至大型服务器上的web服务,各种应用都有在使用Java SE,为了支持这种多样化的部署,Java HotSpot VM提供了多种垃圾收集器,旨在满足不同的需求。这是能既满足大型应用需求也满足小型应用需求的重要原因之一。Java SE基于运行应用的机器的类别选择最合适的垃圾收集器。但是,这种选择可能并非对每个应用都是最佳的。 对性能目前有严格要求或有其他要求的用户、开发人员和管理员可能需要显式选择垃圾回收器并调整某些参数以实现期望的性能水平。本文档提供了有助于完成这些任务的信息。首先,在串行、stop-the-world 的上下文中描述了垃圾收集器的一般功能和基本调节选项。然后介绍其他收集器的特定功能以及选择收集器时要考虑的因素。
垃圾收集器(GC)是一种内存管理工具。它通过以下操作实现自动内存管理:
- 将对象分配给年轻代,并将老的对象提升到老年代。
- 通过并发(并行)标记阶段在老年代中找到存活对象。JVM在整个堆占用量超过默认阈值时触发标记阶段。请参阅CMS收集器和G1收集器章节。
- 通过并行复制压缩存活对象来恢复可用内存。请参阅并行收集器和G1收集器章节。
何时垃圾收集器的选择很重要?对于有些应用,答案是never。即那些在GC的暂停频率和持续时间都适度的情况下运行良好的应用。然而,对于大多数应用程序却不是这种情况,尤其是那些具有大量数据(多个GB),多线程和高事务率的应用程序。
Amdahl定律(给定问题中的并行加速比受问题的同步部分限制)意味着大多数工作负载无法完美并行化;某些部分始终是顺序的,不能从并行中受益。Java平台也是如此。尤其是,Java SE 1.4之前的Oracle 虚拟机不支持并行垃圾收集,因此,垃圾收集对多处理器系统的影响相对于其他并行应用而言更大。
图1-1“比较垃圾收集所花费的时间占比”建模了一个理想的系统,该系统除了垃圾收集(GC)之外,具有完美的可伸缩性。红线表示应用在单处理器系统上仅花费1%的时间进行垃圾回收。在具有32个处理器的系统上,这意味着吞吐量损失超过20%。洋红线显示,应用花费了10%的时间用于垃圾回收(对于单处理器应用来说并不算多),当扩展到32个处理器时,将损失超过75%的吞吐量。
图1-1 比较垃圾收集所花费的时间占比
"图1-1 比较垃圾收集所花费的时间占比"的描述
这表明,在小型系统上开发时可以忽略的速度问题可能会在扩展到大型系统时成为主要瓶颈。但是,在减小这种瓶颈方面进行小的改进可以在性能上获得很大的收益。对于一个足够大的系统,选择正确的垃圾收集器并在需要时进行调整是很值得的。
串行收集器通常适合大多数“小型”应用程序(堆内存需要100MB左右)。其他收集器具有额外的开销或复杂性,这也是特殊行为的代价。如果应用不需要其他可选的收集器的特殊行为,请使用串行收集器。一种不希望串行收集器成为最佳选择的情况是大型,线程密集的应用程序,这些应用程序运行在具有大量内存、两个以上处理器的机器上。当应用运行在此类服务器上时,默认会选择并行收集器,请参见“ 人机工程学(自适应调优) ”章节。
本文档是使用在Solaris操作系统(SPARC Platform Edition)上的Java SE 8作为参考而开发的。但是,本文档介绍的概念和建议适用于所有受支持的平台,包括Linux,Microsoft Windows,Solaris操作系统(x64平台版)和OS X。此外,本文档中的命令行选项在所有支持的平台上都可用,但是某些选项的默认值在不同的平台上可能有所不同。