JVM 中的参数前缀
1、概览
Java 虚拟机(JVM)是驱动 Java 应用的核心引擎,负责执行编译后的 .class
文件,并通过即时编译(JIT)和垃圾回收(GC)等技术管理内存并提升性能。
JVM 具有高度灵活性,通过特定参数可轻松调整其行为以提升性能、排查问题或启用实验性功能。本文将带你了解用于配置 JVM 的不同参数前缀。
2、JVM 参数是什么?
JVM 参数是能改变虚拟机行为的特殊命令行选项,用于控制内存设置、性能调优、调试监控开关、垃圾回收配置及实验性功能。
启动 JVM 时可通过以下方式指定这些参数:
java -Xmx512m -Denv=prod -verbose:gc -XX:+UseG1GC -jar App.jar
上述命令中使用了多种参数前缀,每个前缀标识了不同的配置类型。
-Xmx512m
- 设置最大堆内存为 512 MB(非标准参数)-Denv=prod
- 定义名为env
、值为prod
的系统属性(System Property)-verbose:gc
- 启用垃圾回收日志记录(标准参数)-XX:+UseG1GC
- 指定 JVM 使用 G1 垃圾回收器(高级参数)
下面详细解析各类参数前缀的作用。
3、不同的 JVM 参数前缀
3.1、System Properties (-D)
系统属性(System Properties)通常用于配置 JVM 特定参数,如文件编码、用户目录、JVM 版本等 Java 相关配置。
通过 -D
命令行参数可定义键值对形式的系统属性,例如:
java -Denv=prod -jar App.jar
在 -D
参数前缀中,字母 D 代表 Define(定义)。Java 为避免歧义未使用其他字母,该前缀简短、直观且易记忆,明确表示正在定义属性。
3.2、标准参数(-)
Java 标准参数是经过官方文档记录的配置选项,适用于所有 JVM 实现,用于控制基础行为。这些参数可管理 JVM 的启动和程序运行方式。
例如:
- 使用
-classpath
设置类路径。 - 通过
-version
查看 JVM 版本。
java -version
输出如下:
openjdk version "17.0.14" 2025-01-21 LTS
OpenJDK Runtime Environment Corretto-17.0.14.7.1 (build 17.0.14+7-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.14.7.1 (build 17.0.14+7-LTS, mixed mode, sharing)
在终端执行 java
命令可查看标准参数列表:
Usage: java [options] <mainclass> [args...]
(to execute a class)
or java [options] -jar <jarfile> [args...]
(to execute a jar file)
where options include:
-cp <class search path of directories and zip/jar files>
-classpath <class search path of directories and zip/jar files>
--class-path <class search path of directories and zip/jar files>
A : separated list of directories, JAR archives,
and ZIP archives to search for class files.
To specify an argument for a long option, you can use --<name>=<value> or
--<name> <value>.
3.3、非标准参数(-X)
我们通过 -X
参数访问非标准 JVM 功能(通常用于控制内存和调试行为)。这些参数在不同 JVM 实现(如 OpenJDK、HotSpot 或 Microsoft JVM)中可能存在差异。例如,Red Hat 的 JVM 支持的 -X
参数可能与 Microsoft 不同。
使用以下命令可列出所有非标准选项:
java -X
输出结果取决于 JVM 的实现:
-Xbatch disable background compilation
-Xbootclasspath/a:<directories and zip/jar files separated by :>
append to end of bootstrap class path
-Xcheck:jni perform additional checks for JNI functions
-Xcomp forces compilation of methods on first invocation
-Xdebug does nothing. Provided for backward compatibility.
[...]
这类参数适用于通用调优,但需谨慎使用,因为它们与具体 JVM 实现相关且可能未经通知就发生变化。
3.4、高机参数(-XX)
高级 JVM 参数(以 -XX
开头)用于启用底层或实验性功能,可分为两类:
- 布尔型参数:启用/禁用特定功能(如
-XX:+UseG1GC
启用 G1 垃圾回收器)。 - 赋值型参数:设置自定义值(如
-XX:MaxGCPauseMillis=200
设定最大 GC 停顿时间)。
由于这些参数可能随版本变更、废弃或移除,且不同 JVM 实现支持度各异,使用时需谨慎并关注版本更新。
以下示例通过高级参数优化垃圾回收行为以提升响应速度:
java -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -jar App.jar
此处我们首先指示 JVM 使用 G1 垃圾回收器,随后要求其将 GC 停顿时间控制在 200 毫秒以内(此为软性目标,JVM 会尽力达成但不保证绝对满足)。
4、JVM 执行模式
下面我们通过不同 JVM 执行模式控制即时编译(JIT)的行为,JIT 会在运行时将 Java 字节码编译为本地机器码并基于运行时分析进行优化。
我们将使用 Benchmark.java
程序进行测试,该程序会向 HashMap
填充 100 万组键值对并检索所有值以验证正确性并测量性能。
public class Benchmark {
private static final int NUM_ENTRIES = 1_000_000;
public static void main(String[] args) {
Benchmark benchmark = new Benchmark();
benchmark.run();
}
public void run() {
HashMap<Integer, String> map = new HashMap<>();
// 填充 HashMap
long startPut = System.nanoTime();
for (int i = 0; i < NUM_ENTRIES; i++) {
map.put(i, "Value" + i);
}
long endPut = System.nanoTime();
System.out.println("Time to put: " + (endPut - startPut) / 1_000_000 + " ms");
// 从 HashMap 中检索
long startGet = System.nanoTime();
for (int i = 0; i < NUM_ENTRIES; i++) {
String value = map.get(i);
if (value == null) {
System.err.println("Missing key: " + i);
}
}
long endGet = System.nanoTime();
System.out.println("Time to get: " + (endGet - startGet) / 1_000_000 + " ms");
}
}
4.1、-Xint - 纯解释模式
-Xint
标志强制 JVM 以纯解释模式运行所有字节码,完全禁用 JIT 编译,导致执行速度显著下降。
该模式适用于调试时隔离 JIT 相关问题,或对比 JIT 编译与纯解释模式的性能差异。
以下是解释模式的性能表现:
java -server -showversion -Xint Benchmark
openjdk version "17.0.14" 2025-01-21 LTS
OpenJDK Runtime Environment Corretto-17.0.14.7.1 (build 17.0.14+7-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.14.7.1 (build 17.0.14+7-LTS, interpreted mode, sharing)
Time to put: 1532 ms
Time to get: 261 ms
4.2、-Xcomp - 纯编译模式
-Xcomp
标志强制 JVM 在首次使用时编译所有方法(而非等待识别热点方法)。虽然这能完全避免解释器的性能损耗,但激进编译会导致启动变慢(长期可能获得性能收益)。
以下是纯编译模式的性能表现:
java -server -showversion -Xcomp Benchmark
openjdk version "17.0.14" 2025-01-21 LTS
OpenJDK Runtime Environment Corretto-17.0.14.7.1 (build 17.0.14+7-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.14.7.1 (build 17.0.14+7-LTS, compiled mode, sharing)
Time to put: 1167 ms
Time to get: 10 ms
4.3、-Xmixed - 默认模式
混合模式(默认)会先解释执行代码,随后通过 JIT 编译器优化热点方法。这种设计平衡了启动时间和长期性能,兼具两者优势。
现代 HotSpot 版本已默认启用混合模式,无需手动指定参数。以下是其性能表现:
java -server -showversion Benchmark
openjdk version "17.0.14" 2025-01-21 LTS
OpenJDK Runtime Environment Corretto-17.0.14.7.1 (build 17.0.14+7-LTS)
OpenJDK 64-Bit Server VM Corretto-17.0.14.7.1 (build 17.0.14+7-LTS, mixed mode, sharing)
Time to put: 75 ms
Time to get: 12 ms
测试结果表明,默认的混合模式在启动时间和运行时性能之间取得了最佳平衡。解释模式 -Xint
速度显著较慢,主要用于调试或分析场景。编译模式 -Xcomp
虽能减少热点路径的执行时间,但会带来更高的启动开销。
4.4、-Xverify - 字节码验证控制
Java 代码编译为字节码后,JVM 会在执行前进行字节码验证,确保代码符合 JVM 规范、正确使用栈结构、安全访问变量并维持合规控制流。此步骤能有效预防崩溃和安全风险(尤其运行不可信或第三方代码时)。
-Xverify
选项用于控制字节码验证的时机与方式:
-Xverify:all
(默认):加载时验证所有类,保障执行安全性与正确性。-Xverify:none
:跳过加载时验证,可能略微提升启动速度,但会降低安全性(存在风险)。
示例风险场景:
java -Xverify:none -cp app.jar com.baeldung.Main
我们可以通过 VisualVM 和 Java 管理扩展(Java Management Extensions,JMX)实现 Java 应用的远程监控。
5、总结
本文介绍了各类 JVM 参数前缀。JVM 执行模式同样属于非标准参数范畴,其中混合模式为常规应用提供了最高效稳定的运行方式。合理配置 JVM 参数可提升应用性能、增强稳定性并简化调试流程。
Ref:https://www.baeldung.com/java-jvm-arguments-prefixes