在正在运行的JVM中,如何以编程方式确定启动时使用的jvm选项?

Mic*_*lot 9 java jvm jvm-arguments

背景:我正在对通过多层间接启动的Java应用程序进行一些性能测试,这样我就不能完全确定应用程序是否会使用我认为的标志启动.我希望我的应用程序包括一个健全性检查(在它开始性能测试之前)并在结果中(在测试之后)包含有关如何调整JVM的信息,例如:

  • 使用了哪个垃圾收集器?
  • 是/它是否正在积极进行cpu性能分析?
  • 是/是否记录了gc活动?
  • 是/是它-Xint还是-Xmixed模式?
  • 是/已-XX:ParallelGCThreads设置 - 如果是,如果是,如果没有,这个构建的默认值是什么?
  • 是/正在-XX:UseCompressedOops开启或关闭?
  • 等等

有没有办法让Java代码(在正在运行的JVM中)查询用于包含JVM的实际选项?(假设我看不到启动我的命令行,所以我无法重新解析那些标志.)

如果没有通用的方法来确定这一点,那么也欢迎特定于特定JVM实现的答案.

更新:

对于解决方案而言,重要的是能够知道命令行中未明确提供的任何值的默认值.否则,它将涉及很多(容易出错的)腿部工作,以查找给定组合JVM /平台/版本/体系结构的默认值.我正在测试各种各样的JVM,所以我不想手动找出每个jvm版本中每个参数的默认设置.

Zho*_*gYu 6

您可以通过获取命令行参数

ManagementFactory.getRuntimeMXBean().getInputArguments();
Run Code Online (Sandbox Code Playgroud)


Tre*_*son 5

以下 Java 7 代码将列出 . 返回的所有 JVM 选项-XX:+PrintFlagsFinal。它尝试使用反射来访问受包保护的帮助器类(自 Java 6 起可用),如果不起作用,则Flag回退到该类。HotSpotDiagnosticMXBean.getDiagnosticOptions()

// load the diagnostic bean first to avoid UnsatisfiedLinkError
final HotSpotDiagnosticMXBean hsdiag = ManagementFactory
        .getPlatformMXBean(HotSpotDiagnosticMXBean.class);
List<VMOption> options;
try {
    final Class<?> flagClass = Class.forName("sun.management.Flag");
    final Method getAllFlagsMethod = flagClass.getDeclaredMethod("getAllFlags");
    final Method getVMOptionMethod = flagClass.getDeclaredMethod("getVMOption");
    getAllFlagsMethod.setAccessible(true);
    getVMOptionMethod.setAccessible(true);
    final Object result = getAllFlagsMethod.invoke(null);
    final List<?> flags = (List<?>) result;
    options = new ArrayList<VMOption>(flags.size());
    for (final Object flag : flags) {
        options.add((VMOption) getVMOptionMethod.invoke(flag));
    }
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException
        | InvocationTargetException | ClassCastException e) {
    if (hsdiag != null) {
        // only includes writable external flags
        options = hsdiag.getDiagnosticOptions();
    } else {
        options = Collections.emptyList();
    }
}
final Map<String, VMOption> optionMap = new TreeMap<>();
for (final VMOption option : options) {
    optionMap.put(option.getName(), option);
}
for (final VMOption option : optionMap.values()) {
    System.out.println(option.getName() + " = " + option.getValue() + " (" +
            option.getOrigin() + ", " +
            (option.isWriteable() ? "read-write" : "read-only") + ")");
}
System.out.println(options.size() + " options found");
Run Code Online (Sandbox Code Playgroud)

使用 7u71,我有 663 个选项,或者使用-XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions779。


Ale*_*leš 2

您可以使用 JMX 客户端(如 VisualVM),然后调用getVMOption(String name),请参阅HotSpotDiagnosticMXBean

或者,如果您可以传入至少一组标志来启用 JVM 日志记录,那么应该--XX:+LogVMOutput -XX:LogFile=jvm.log然后解析应用程序的日志输出。该日志包含用于启动 JVM 的所有标志/参数。

另一种选择是列出由 PID 启动的JVM 进程ps -ef,您可以在其中看到该进程的所有输入参数。这应该适用于任何 JVM 类型。