如何从Java应用程序内部获取虚拟机参数?

196

我需要检查是否已明确设置了可以传递给JVM的某些选项,或者其具有默认值。

更具体地说:我需要创建一个具有比默认线程更高的本机堆栈大小的特定线程,但是如果用户希望通过指定-Xss选项自己处理此类事情,则希望创建所有具有默认堆栈大小的线程(这将由用户在-Xss选项中指定)。

我已经检查了诸如java.lang.Systemjava.lang.Runtime之类的类,但它们并未向我提供有关VM参数的任何有用信息。

有没有办法获取我需要的信息?

5个回答

230

在启动时传递这个参数 -Dname=value

然后在你的代码中应该使用:

value=System.getProperty("name");

获取该值


6
我不能使用这个来获取 -Xdebug。 - petertc
41
不确定为什么这个答案会被投票得这么高,它只检索应用程序参数(使用“-D”指定的参数),而不是VM参数(使用“-X”指定的参数)。问题特别涉及“-X”参数。 - cleberz
11
我来这里是因为我认为 -Dname=value 类型的参数是 JVM 参数,与 -X 参数没有本质区别。实际上,它们都被传递给 java,而不是应用程序在命令行中,例如,在 maven 中,你可以将它们作为 -Drun.jvmArguments=... 传递。我相信这就是为什么它会得到赞同的原因。 - kap
2
这完全没有回答原帖作者的需求。 - dan.m was user2321368
6
可能是这样!但当搜索“如何在代码中读取VM选项”时,它会出现在谷歌搜索结果的前面,这就是它相关的原因。 - 62mkv
显示剩余4条评论

226

使用此代码,您可以获取JVM参数:

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
...
RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
List<String> arguments = runtimeMxBean.getInputArguments();

@Daniel,这应该可以让你得到主类的名称:
final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
final String mainClassName = stackTrace[stackTrace.length - 1].getClassName());
- laz
4
如果您确保正在使用 Oracle 的 JVM 运行,并且有解析参数的代码,那将非常有用。 - laz
4
@Vulcan并不包括VM参数。它包含主类名和传递给main方法的参数数组。 - dacongy
仅供记录,我在Java 1.6.0_25和JVM参数值中有空格字符的情况下遇到了问题,这种方法会为其中一个JVM参数返回多个条目,但在Java 1.7.0_21中没有出现此问题。 - Jaime Hablutzel
@laz 假设您在主线程中。 - nafg
显示剩余2条评论

7
我发现 HotSpot 在管理 bean 中列出了除 -client 和 -server 以外的所有 VM 参数。因此,如果您从 VM 名称推断出 -client/-server 参数,并将其添加到运行时管理 bean 的列表中,您就会得到完整的参数列表。
以下是 SSCCE:
import java.util.*;
import java.lang.management.ManagementFactory;

class main {
  public static void main(final String[] args) {
    System.out.println(fullVMArguments());
  }

  static String fullVMArguments() {
    String name = javaVmName();
    return (contains(name, "Server") ? "-server "
      : contains(name, "Client") ? "-client " : "")
      + joinWithSpace(vmArguments());
  }

  static List<String> vmArguments() {
    return ManagementFactory.getRuntimeMXBean().getInputArguments();
  }

  static boolean contains(String s, String b) {
    return s != null && s.indexOf(b) >= 0;
  }

  static String javaVmName() {
    return System.getProperty("java.vm.name");
  }

  static String joinWithSpace(Collection<String> c) {
    return join(" ", c);
  }

  public static String join(String glue, Iterable<String> strings) {
    if (strings == null) return "";
    StringBuilder buf = new StringBuilder();
    Iterator<String> i = strings.iterator();
    if (i.hasNext()) {
      buf.append(i.next());
      while (i.hasNext())
        buf.append(glue).append(i.next());
    }
    return buf.toString();
  }
}

如果您希望参数以 List<String> 的形式呈现,可以缩短代码。

最后需要注意的是:我们可能还需要扩展此功能以处理命令行参数中包含空格的罕见情况。


好的,刚刚完成了。谢谢 :) - Stefan Reich

3

2
如果你想要获取Java进程的完整命令行,你可以使用:JvmArguments.java(它使用JNA + /proc的组合来覆盖大多数Unix实现)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接