探索高级 JVM 选项

在本文中,我们全面探讨了高级 JVM 选项,结合了全文讨论中引用的见解和所提出的分析。

我们观察了高级 JVM 参数以及它们如何增强垃圾收集、内存管理和运行时性能。虽然配置范围可能让人感到不知所措,但我们提到 JVM 人体工程学是一种有用的解决方案,可以简化调优过程并优化应用程序性能。

Java 虚拟机 (JVM) 是支持 Java 应用程序的强大引擎。它具有高度可定制性,通过标准选项提供基本配置,通过非标准选项提供常规性能调优,通过高级选项提供精确控制。

高级选项允许开发人员微调性能,诊断问题并试验尖端功能。

在本教程中,我们将探索最著名的高级 JVM 选项及其使用方法,从而让我们能够更细粒度地控制 JVM 行为。

JVM选项的分类
JVM 参数主要可以分为三类:

  • 标准选项(-version、-help)
  • 非标准选项(-X:选项)
  • 高级选项(-XX:选项)

了解高级 JVM 选项
高级选项超越了基本配置,可以设置 JVM 的低级属性。这些选项允许我们调整性能关键参数,例如垃圾收集、内存管理和运行时诊断。
其中一些高级选项也是最常用的最重要的 JVM 参数之一。了解如何在 IntelliJ 中设置这些 JVM 选项对于调整 JVM 以进行开发和调试大有裨益。

然而,由于它们针对特定应用场景提供了微调,我们必须谨慎使用它们。在没有清楚了解应用程序行为的情况下进行过度定制可能会导致性能不佳、崩溃或意外行为。

此外,高级 JVM 选项不保证所有 JVM 实现都支持,并且可能会发生变化。因此,由于这些选项会随着 JVM 更新而演变,因此某些选项可能会在较新版本中被弃用或表现不同。

例如,Java 并发标记和清除垃圾收集算法就曾出现过这种情况,该算法在 Java 9 中已弃用,并在 Java 14 中被删除。通过监视文档,我们可以在任何更改发生之前随时了解情况。

现在让我们通过不同的类别探索各种高级 JVM 选项。

垃圾回收调优
垃圾收集对于内存管理至关重要,但可能会造成影响性能的暂停。高级选项可控制垃圾收集行为,确保应用程序运行更顺畅。
自 Java 9 以来,默认设置是垃圾优先垃圾收集器(G1),旨在平衡吞吐量和延迟。

为了克服 G1 的延迟限制,JDK12 引入了Shenandoah GC,可以使用-XX:+UseShenandoahGC选项启用。Shenandoah的可用性取决于 JDK 供应商和版本。

可以根据专门的工作负载使用其他实现。Epsilon垃圾收集器也非常适合性能调优,可以检查垃圾收集是否影响我们程序的性能。
前面引用的主题探讨了用于垃圾收集的各种有用的高级 JVM 选项。

内存管理
正如我们上面讨论的,垃圾收集是内存管理的重要组成部分,但它只是 JVM 中更大的内存管理生态系统的一部分。

为了获得最佳性能,配置内存分配、管理堆大小以及了解堆外内存的工作原理同样重要,尤其是对于内存密集型应用程序或具有特定性能要求的系统。

现在,让我们回顾一下与内存管理相关的一些高级 JVM 选项:

  • -XX:InitialHeapSize和-XX:MaxHeapSize – 这些选项定义初始和最大堆大小(以字节为单位)
  • -XX:MetaspaceSize和-XX:MaxMetaspaceSize – 这些选项定义元空间区域的初始和最大大小
  • -XX:InitialRAMPercentage和-XX:MaxRAMPercentage – 这些选项将初始和最大堆大小定义为系统可用内存的百分比。这些设置允许 JVM 动态扩展其内存使用量,从而提供更好的适应性
  • -XX:MinHeapFreeRatio和-XX:MaxHeapFreeRatio – 这些选项定义 GC 周期后堆中维护的可用空间的最小和最大百分比
  • -XX:+AlwaysPreTouch – 通过在 JVM 初始化期间预触碰 Java 堆来减少延迟。因此,每个堆页面都在 JVM 启动时初始化,而不是在应用程序执行期间逐步初始化
  • -XX:MaxDirectMemorySize – 定义可为直接字节缓冲区保留的内存量
  • -XX:CompressedClassSpaceSize – 定义使用压缩类指针( -XX:-UseCompressedClassPointers)时在元空间中存储类元数据所分配的最大内存

即时编译
即时 (JIT) 编译是 JVM 的一个重要组件,可在运行时将字节码编译为本机机器码,从而提高 Java 应用程序的性能。JIT 编译器默认启用,除非为了调查 JIT 编译问题,否则不建议禁用它。

让我们回顾一下用于配置和调整 JIT 编译的高级 JVM 选项:

  • -XX:CICompilerCount – 定义用于 JIT 编译的编译器线程数。默认值与可用 CPU 和内存的数量成正比
  • -XX:ReservedCodeCacheSize – 定义用于存储 JIT 编译的本机代码的内存区域的最大大小
  • -XX:CompileThreshold – 定义方法首次编译之前的方法调用次数
  • -XX:MaxInlineSize – 定义 JIT 编译器可以内联的方法的最大允许大小(以字节为单位)

诊断和调试
诊断和调试对于识别和解决 Java 应用程序中的问题(例如性能瓶颈、内存泄漏和意外行为)至关重要。

让我们回顾一下与诊断和调试相关的高级 JVM 选项,这些选项可以帮助我们更深入地了解应用程序的行为和性能:

  • -XX:+HeapDumpOnOutOfMemoryError –发生OutOfMemoryError时生成堆转储
  • -XX:HeapDumpPath – 定义保存堆转储的文件路径
  • -XX:+PrintCompilation – 记录 JIT 编译
  • -XX:+LogCompilation – 将详细的 JIT 编译日志写入文件
  • -XX:+UnlockDiagnosticVMOptions – 解锁默认情况下不可用的诊断 JVM 选项
  • -XX:+ExitOnOutOfMemoryError – 遇到OutOfMemoryError时强制 JVM 立即退出
  • -XX:+CrashOnOutOfMemoryError – 强制 JVM 生成核心转储并在发生OutOfMemoryError时崩溃
  • -XX:ErrorFile – 定义发生不可恢复的错误时保存错误数据的文件路径
  • -XX:NativeMemoryTracking – 定义跟踪 JVM 本机内存使用情况的模式(关闭/摘要/详细)
  • -XX:+PrintNMTStatistics – 在 JVM 退出时启用打印收集的本机内存跟踪数据。仅当启用本机内存跟踪时才可使用 ( -XX:NativeMemoryTracking )

用于记录 GC 信息的高级 JVM 选项-XX:+PrintGC和-XX:+PrintGCDetails自 Java 9 以来已被弃用,应该用统一日志记录选项-Xlog替换。

人体工程学
我们探索了许多强大的高级 JVM 选项,这可能会让我们觉得配置和调整 JVM 以满足我们的特定要求是一件非常困难的事情。JVM通过人体工程学提供了一种解决方案,可以根据底层硬件和运行时条件自动调整其行为,从而提高应用程序的性能。

让我们列出我们环境中的所有人体工程学默认值:
java -XX:+PrintFlagsFinal -version

然而,尽管人体工程学旨在设置合理的默认值,但它们可能并不总是符合我们的应用程序的需求。