Sun 开发、HP 移植的 HotSpot Java™ 虚拟机 (JVM) 的体系结构已经以不同于
IBM 开发的 Software Development Kit (SDK) 的方式发展。其年轻代或年老代和持久代区域的内部结构提升为主要支持分代垃圾回收,以及必要时支持其他垃圾回收方式。
开始之前
注: 本主题引用了一个或多个应用程序服务器日志文件。作为另一种建议采用的方法,您可以在分布式系统和 IBM® i 系统上配置服务器以使用高性能可扩展日志记录 (HPEL) 记录和跟踪基础结构,而不使用 SystemOut.log、SystemErr.log、trace.log 和 activity.log 文件。您还可以将 HPEL 与本机 z/OS® 日志记录设施结合使用。如果要使用 HPEL,那么可从服务器概要文件
bin 目录使用 LogViewer 命令行工具来访问所有日志和跟踪信息。有关使用
HPEL 的更多信息,请参阅有关使用 HPEL 对应用程序进行故障诊断的信息。
关于此任务
调整 Sun HotSpot JVM 是一个反复进行的过程,在该过程中会开发
JVM 配置、收集数据(主要从 verbosegc 数据收集)然后进行分析并在下一个循环应用任何配置修订。如果需要调整
Sun HotSpot JVM,请执行下列一个或多个步骤。
过程
- 提供足够的 Java 堆内存。
Java 堆内存是一组保留的连续地址。Java 堆内存的大小是为 Java 堆配置的最大大小。这些地址不可用于其他本机内存需求或系统内存需求,并且只由
JVM 维护和管理,因为 Java 堆用于在该 JVM 的生命周期内存储 Java 对象。
JVM 初始化时,将根据 JVM 配置设置获取 Java 堆的安全资源。如果可用的内存不足,那么
JVM 初始化将会失败。如果在 Java 堆中配置的内存不足,那么系统最终将失败并生成
OutOfMemory 报告,在此失败发生之前通常有相当大的垃圾回收活动,在此活动期间几乎没有进行任何
Java 处理。
必须充分考虑进程其他组件的本机内存需要,以容纳运行中的线程、存储
I/O 数据并满足对齐和页大小等要求。
Sun HotSpot Java 堆由物理上独立的两个部分组成(指定最大 Java 堆大小时必须考虑到这一点):
- 持久代区域,它是进一步细分为 eden、survivor
spaces 和 tenured 区域的年青代区域和年老代区域的组合。
- 此系统的 Java 组件的供应内存。
-XX:MaxPermSize= 和 -Xmx(最大 Java 堆大小)参数分别配置永久区域(其中类代码和相关数据在逻辑上表示为年老代区域的一部分,但物理上单独保存)的最大大小和主堆(其中 Java 对象及其数据存储在年轻代区域或年老代区域中)的最大大小。永久区域和主堆一起组成整个
Java 堆。任一区域中的分配失败表示不能容纳所有应用程序代码或所有应用程序数据,这两种情况都是会导致耗尽可用存储器并导致
OutOfMemory 错误的终止条件。
考虑下列调整参数:
- -XX:MaxPermSize(永久区域)
- -Xmx(最大 Java 堆大小)
- 禁用显式垃圾回收以消除任何不必要或不合时宜的主要垃圾回收循环(这些循环可能会引入系统的软件组件)。
考虑调整参数 -XX:+DisableExplicitGC。
避免故障: 缺省情况下,当一个类没有任何活动实例可用时,JVM 就会从内存中卸装该类。可以使用
-Xnoclassgc 参数来禁用类垃圾回收。但是,类垃圾回收的性能影响通常很小,在基于 Java Platform, Enterprise
Edition (Java EE) 的系统(该系统大量使用应用程序类装入器)中关闭类垃圾回收可能会在事实上造成类数据的内存泄漏并导致 JVM 抛出内存不足异常。
如果使用 -Xnoclassgc 参数,那么每当必须重新部署应用程序时,始终应重新启动应用程序服务器,以清除来自先前版本的应用程序的类和静态数据。
gotcha
如果使用 -Xnoclassgc 参数,那么每当必须重新部署应用程序时,始终应重新启动应用程序服务器,以清除来自先前版本的应用程序的类和静态数据。
- 调整区域大小以优化垃圾回收操作。
任何垃圾回收调整尝试决策都应基于垃圾回收器的行为。应确定正确的垃圾回收方式以满足应用程序的操作需要。还应验证是否满足性能要求,以及是否高效回收足够的内存资源以保持满足应用程序需求。对垃圾回收参数设置进行的任何更改都应产生明显不同的结果并显示利用
HotSpot Java 堆的不同区域所获得的益处。
不明智的选择通常会延长调整过程,因为反复进行的调整过程需要重复相当多的次数。后面各节显示两个主要选项(并行吞吐量或并发低暂停)以及进行进一步调整的相关选项。两种方式都有可能提供高性能,但是对于每种方式,可以优化行为的关键性能因素不相同。
主要调整活动考虑控制资源使用率以处理应用程序的分配活动,以及安排高效的垃圾回收以根据需要回收存储器。这些调整讨论不可避免地依赖于所使用的垃圾回收方式。讨论了两种类型的垃圾回收:
- 吞吐量回收器,它在年轻代上执行并行清理复制回收。此类型的垃圾回收是多处理器服务器类机器上的缺省类型。
- 并发低暂停回收器。
使用这些回收器进行调整的目标是提供最适合应用程序系统的分配模式和对象生存期的行为,以及尽量提高其回收操作的效率。
- 选项 1:在启用内置调整的情况下使用缺省吞吐量/并行清理回收器。
从 V5 开始,Sun HotSPot JVM 提供了一些检测运行服务器的操作系统的功能,并且
JVM 尝试根据是否存在多个处理器以及物理内存的大小,设置适当的分代垃圾回收方式(并行或串行)。产品以生产或预生产方式运行所基于的硬件应满足可视为服务器类机器的要求。但是,一些开发硬件可能不满足此条件。
吞吐量垃圾回收器无论是否进行了自动调整,其行为都保持相同,并且当它尝试最大程度地提高分代垃圾回收的益处时,会将一些时间相当长(与所用堆大小成比例)的暂停引入到 Java 应用程序系统的执行过程中。但是,这些自动算法不能确定工作负载是否很适合其操作、系统是否需要其他垃圾回收策略或者其他垃圾回收策略是否更合适。
考虑下列调整参数:
- -XX:+UseParallelGC
- -XX:+UseAdaptiveSizePolicy
- -XX:+AggressiveHeap
- 选项 2:使用缺省缺省吞吐量/并行清理回收器,但手动调整。
使用通过 -XX:+UseAdaptiveSizePolicy 参数建立的内置算法的缺点包括限制可配置以与内置算法配合使用的其他参数(例如
-XX:SurvivorRatio 参数)。使用内置算法时,会放弃一些确定在执行期间使用的资源分配的控制权。如果对使用内置算法的效果不满意,那么手动配置
JVM 资源比尝试调整算法的操作容易一些。手动配置 JVM
资源所需使用的选项是调整算法的操作所用选项的一半。
考虑下列调整参数:
- -XX:NewRatio=2(这是对 VM 方式配置的服务器的缺省值)
- -XX:MaxNewSize= 和 -XX:NewSize=
- -XX:SurvivorRatio=
- -XX:+PrintTenuringDistribution
- -XX:TargetSurvivorRatio=
- 选项 3:使用并发低暂停标记-清除回收器
此回收器是加强 Hotspot 体系结构的分代垃圾回收发展的辐射散布,它允许用专用的低优先级后台垃圾回收线程覆盖应用程序线程处理。如果您的应用程序数据与缺省吞吐量回收器的行为不兼容,那么并发标记-清除
(CMS) 回收器可能是切实可行的策略,对于不能容忍切入暂停的应用程序系统尤其如此。此回收器对于以下项尤其有用:与
64 位 JVM 配合使用的超大堆;具有大量长期生存的数据集(也称为大型持久年老区代)且保持相当好的高速缓存使用率、大量保留年轻代页,即使后台线程必须扫描整个堆的所有页时也是如此的应用程序。
要将并发标记-清理回收器用作主要的内务处理代理程序,请将此选项而不是任何其他垃圾回收方式添加至 JVM 配置。
考虑下列调整参数:
- -XX:+UseConcMarkSweepGC
- -XX:CMSInitiatingOccupancyFraction=75
- -XX:SurvivorRatio=6
- -XX:MaxTenuringThreshold=8
- -XX:NewSize=128m
调整 CMS 的难点包括最坏情况垃圾回收时间(即 CMS 循环异常终止时的情况)可能会持续几秒钟,这对于精确使用
CMS 以避免长暂停的系统代价尤其高昂。因此,服务级别协议可能会要求使用
CMS,因为平均或中值暂停时间极短,并且调整时必须十分小心,以确保 CMS 循环不会异常终止。仅当
CMS 的预期性触发器确保 CMS 循环始终提前启动足够早,可以确保在需要资源时有足够的可用资源可供使用,这样
CMS 才能成功。如果在年老区代填满前 CMS 回收器无法完成,那么会通过暂停应用程序线程来完成回收,这称为完全回收。完全回收表示需要进一步调整
CMS 回收器,以便它更适合您的应用程序。
最后,与具有压缩阶段的其他垃圾回收方式不同,使用
CMS 理论上会提高 HotSpot 发生分段的风险。但是,在回收恢复堆正常合理的比例时,这实际上很少会造成问题。在
CMS 失败或者异常终止回收的情况下,将会触发备用压缩垃圾回收。与普通
CMS 回收相比,任何其他类型的垃圾回收不可避免地招致明显的切入暂停。
避免故障: 与吞吐量回收器一样,可使用相当多的选项来显式控制 CMS。但是,提到的那些选项表示在调整
HotSpot JVM 时很可能要考虑使用的核心选项。
gotcha
下一步做什么
收集并分析数据以评估配置(通常使用 verbosegc)。在进行调整更改时继续收集和分析数据,直到对 JVM 的执行效果满意为止。