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

时间:2013-06-07 23:58:47

标签: java jvm jvm-arguments

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

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

Java代码是否有任何方法(在正在运行的JVM中)查询用于包含JVM的实际选项? (假设我看不到启动我的命令行,所以我无法重新解析这些标志。)

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

更新:

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

3 个答案:

答案 0 :(得分:6)

您可以通过

获取命令行参数
ManagementFactory.getRuntimeMXBean().getInputArguments();

答案 1 :(得分:2)

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

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

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

答案 2 :(得分:2)

以下Java 7代码将列出-XX:+PrintFlagsFinal返回的所有JVM选项。它尝试使用反射来访问受包保护的Flag帮助程序类(自Java 6以来可用),如果不起作用,则会回退到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");

使用7u71,我可以获得663个选项,或使用-XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions,779。