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 实现(如 OpenJDKHotSpotMicrosoft 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