从台式机上的小applet到大型服务器上的web服务,各种各样的应用程序都使用Java平台标准版(Java SE)。为了支持这种不同的部署范围,Java HotSpot VM提供了多个垃圾收集器,每个垃圾收集器都是为了满足不同的需求而设计的。Java SE根据运行应用程序的计算机类选择最合适的垃圾收集器。但是,这种选择可能并不适合每个应用程序。具有严格性能目标或其他需求的用户、开发人员和管理员可能需要显式地选择垃圾收集器并调优某些参数以实现所需的性能级别。本文档提供了帮助完成这些任务的信息。

首先,在串行停止式收集器上下文中描述了垃圾收集器的一般特性和基本调优选项。然后介绍其他收集器的具体特性以及在选择收集器时要考虑的因素。

什么是垃圾收集器?

垃圾收集器 (GC) 自动管理应用程序的动态内存分配请求,垃圾收集器通过以下操作执行自动动态内存管理

  • 从操作系统分配内存并将其还给操作系统
  • 在应用程序请求它时将该内存分发给应用
  • 确定应用程序仍在使用该内存的哪些部分
  • 回收未使用的内存以供应用程序来重用

Java HotSpot 垃圾收集器采用各种技术来提高这些操作的效率

  • 将分代清理与老化结合使用,将精力集中在堆中最有可能包含大量可回收内存区域的区域
  • 使用多个线程积极地使操作并行,或者在后台执行一些与应用程序并发的长时间运行的操作
  • 尝试通过压缩活动对象来恢复更大的连续可用内存

为什么垃圾收集器的选择很重要?

垃圾收集器的目的是将应用程序开发人员从手动动态内存管理中解放出来。开发人员无需将分配与释放进行匹配,并密切关注分配的动态内存的生命周期。这以一些额外的运行时开销为代价完全消除了与内存管理相关的某些类别的错误。Java HotSpot VM 提供了一系列可供选择的垃圾收集算法。

垃圾收集器的选择何时重要?对于某些应用程序,答案是永远不会。也就是说,应用程序可以在垃圾收集存在且具有适度频率和持续时间的暂停的情况下良好运行。但是,对于一些应用程序而言,情况并非如此,尤其是那些具有大量数据(数 GB)、许多线程和高事务率的应用程序

Amdahl 定律(给定问题中的并行加速受到问题的串行部分的限制)意味着大多数工作负载不能完全并行化;某些部分始终是串行的,并且不会从并行性中受益。在 Java 平台中,目前有四种受支持的垃圾收集替代方案,除了其中之一,串行 GC 之外的所有替代方案都可以并行化工作以提高性能保持尽可能低的垃圾收集开销非常重要。这可以在以下示例中看到。

图 1-1 中的图形模拟了一个理想的系统,除了垃圾收集之外,该系统具有完美的可扩展性。红线表示在单处理器系统上只花费1%的时间用于垃圾收集的应用程序。这意味着在具有32个处理器的系统上,吞吐量损失超过20%。洋红色的线条显示,对于垃圾收集时间占10%的应用程序(在单处理器应用程序中,垃圾收集时间不算多),当扩展到32个处理器时,超过75%的吞吐量损失。

image.png

该图表明,在小型系统上开发时可忽略的吞吐量问题可能会成为扩展到大型系统时的主要瓶颈。然而,减少这种瓶颈的小改进可以产生巨大的性能提升。对于足够大的系统,选择正确的垃圾收集器并在必要时对其进行调整变得值得。


串行收集器通常适用于大多数小型应用程序,特别是那些在现代处理器上需要高达大约 100 MB 的堆的应用程序。其他收集器有额外的开销或复杂性,这是特殊行为的代价。如果应用程序不需要备用收集器的特殊行为,请使用串行收集器。串行收集器不是最佳选择的一种情况是在具有大量内存和两个或更多处理器的机器上运行的大型、多线程应用程序。当应用程序在此类服务器级机器上运行时,默认选择垃圾优先(G1)收集器;参见人体工程学。