JVM 中的高级选项
1、概览
Java 虚拟机(JVM)是驱动 Java 应用程序的强大引擎。它具有高度可定制性,通过标准选项提供基本配置,通过非标准选项进行一般性性能调优,以及通过高级选项实现精确控制。
高级选项允许开发人员对性能进行微调,诊断问题,并尝试最前沿的功能。
本文将带你了解最著名的高级 JVM 选项以及如何使用它们,从而对 JVM 行为进行更精细的控制。
2、JVM 选项的分类
JVM 参数可分为三大类:
- 标准选项(-version、-help)
- 非标准选项(-X: options)
- 高级选项(-XX: options)
3、理解高级 JVM 选项
高级选项不仅限于基本配置,还可以设置 JVM 的更低级属性。这些选项允许我们调整性能关键参数,如垃圾回收、内存管理和运行时诊断。
其中一些高级选项也是常用的最重要的 JVM 参数。不过,由于它们可以针对特定应用场景进行微调,我们必须谨慎使用。在不清楚应用程序行为的情况下过度定制,可能会导致性能低下、崩溃或意外行为。
此外,高级 JVM 选项并不能保证为所有 JVM 实现所支持,而且可能会发生变化。因此,由于这些选项会随着 JVM 的更新而变化,有些选项可能会过时,或者在较新版本中表现不同。
例如,Java 并发标记和清理垃圾收集(CMS)算法就曾出现过这种情况,该算法在 Java 9 中被弃用,并在 Java 14 中被删除。通过关注官方文档,我们可以在发生任何变化之前及时了解情况。
4、垃圾收集调整
垃圾回收对内存管理至关重要,但也会带来影响性能的停顿。高级选项可控制垃圾回收行为,确保应用程序运行更流畅。
从 Java 9 开始,默认情况下使用垃圾优先的垃圾收集器(G1),旨在平衡吞吐量和延迟。
为了克服 G1 的延迟限制,JDK12 引入了 Shenandoah GC,可以使用 -XX:+UseShenandoahGC
选项启用它。Shenandoah 的可用性取决于 JDK 供应商和版本。
还可以根据专门的工作负载使用其他实现方式。Epsilon 垃圾收集器也非常适合用于性能调优,以检查垃圾收集是否会影响我们程序的性能。
5、内存管理
如上所述,垃圾回收是内存管理的重要组成部分,但它只是 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
)时,为在元空间中存储类元数据分配的最大内存。
6、即时编译(JT)
即时编译(JIT)是一个重要的 JVM 组件,可在运行时将字节码编译为本地机器码,从而提高 Java 应用程序的性能。JIT 编译器在默认情况下是启用的,除非是为了调查 JIT 编译问题,否则最好不要禁用它。
回顾一下用于配置和调整 JIT 编译的高级 JVM 选项:
-XX:CICompilerCount
:定义用于 JIT 编译的编译器线程数。默认值与可用 CPU 和内存的数量成正比。-XX:ReservedCodeCacheSize
:定义分配用于存储 JIT 编译的本地代码的内存区域的最大大小。-XX:CompileThreshold
:定义方法首次编译前的方法调用次数(阈值)。-XX:MaxInlineSize
:定义 JIT 编译器可以内联的方法的最大允许大小(以字节为单位)。
7、诊断和调试
诊断和调试对于识别和解决 Java 应用程序中的问题(如性能瓶颈、内存泄漏和意外行为)至关重要。
回顾一下与诊断和调试相关的高级 JVM 选项:
-XX:+HeapDumpOnOutOfMemoryError
:当发生OutOfMemoryError
时生成 Heap Dump。-XX:HeapDumpPath
:定义保存 Heap Dump 的文件路径。-XX:+PrintCompilation
:记录 JIT 编译过程。-XX:+LogCompilation
:将详细的 JIT 编译日志写入文件。-XX:+UnlockDiagnosticVMOptions
:解锁默认情况下不可用的诊断 JVM 选项。-XX:+ExitOnOutOfMemoryError
:强制 JVM 在遇到OutOfMemoryError
时立即退出。-XX:+CrashOnOutOfMemoryError
- 强制 JVM 生成核心 Dump,并在发生OutOfMemoryError
时崩溃。-XX:ErrorFile
:定义发生无法恢复的错误时保存错误数据的文件路径。-XX:NativeMemoryTracking
:定义跟踪 JVM Native 内存使用情况的模式(off/summary/detail)。-XX:+PrintNMTStatistics
:启用在 JVM 退出时打印收集的 Native 内存跟踪数据。只有启用 Native 内存跟踪(-XX:NativeMemoryTracking
)后才能使用。
自 Java 9 起,用于记录 GC 信息的高级 JVM 选项 -XX:+PrintGC
和 -XX:+PrintGCDetails
已被弃用,应由统一日志选项 -Xlog
代替。
8、自适应
上面已经介绍了许多强大的高级 JVM 选项,这些选项可能会让我们在配置和调优 JVM 以满足特定需求时感到不知所措。JVM 通过其自适应机制(Ergonomics)提供了解决方案,它会根据底层硬件和运行时条件自动调整自身行为,从而提升应用程序性能。
列出当前环境中所有的自适应默认值:
java -XX:+PrintFlagsFinal -version
虽然自适应机制旨在设置合理的默认值,但这些默认值不一定总能满足我们的应用需求。
9、总结
本文介绍了常用的一些高级 JVM 参数,以及如何使用它们来提高垃圾回收、内存管理和运行时的性能。
Ref:https://www.baeldung.com/jvm-advanced-options