如何从Java应用程序内部获取VM参数?


162

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

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

我已经检查了类java.lang.Systemjava.lang.Runtime,但是这些类并没有给我有关VM参数的任何有用信息。

有什么方法可以获取我需要的信息吗?

Answers:


183

通过此代码,您可以获取JVM参数:

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

可悲的是,如果在命令行上给出主类的名称,则无法获得它。
丹尼尔(Daniel)2010年

@Daniel,这应该让您获得主要班级的名称: final StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); final String mainClassName = stackTrace[stackTrace.length - 1].getClassName());
laz

3
如果可以保证您可以在Oracle JVM上运行,并且拥有解析这些参数的代码,那么这将很有用。
laz 2012年

2
@Vulcan不会获取VM参数。它包含主类名称和main方法的args数组。
dacongy 2012年

@dacongy我从不暗示VM参数位于sun.java.command系统属性中;我说过,该属性可用于获取主类名称(尽管正如@laz所指出的,我没有提到,该属性仅存在于Oracle的JVM中)。
FThompson,2012年

206

在启动时通过 -Dname=value

然后在代码中应该使用

value=System.getProperty("name");

获得那个价值


4
我不能用它来获取-Xdebug
petertc 2014年

20
不知道为什么这个答案如此之高,它只会检索应用程序参数(由-D指定),而不是VM参数(由-X指定)。问题特别是关于-X参数。
cleberz

4
我之所以来到这里,是因为我相信类型的参数-Dname=value是JVM参数,并且参数之间没有内在的区别-X。实际上,它们都是在命令行而不是在应用程序中传递给java的,例如,在maven中,您可以将as传递给java -Drun.jvmArguments=...。我相信这就是为什么它被赞成。
kap

这根本无法满足原始海报的需求。
dan.m是user2321368'9

4
可能 !但它在搜索“如何读取代码中的VM选项”时在
Google上方

4

我发现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>

最后说明:我们可能还想扩展它,以处理命令行参数中包含空格的罕见情况。


是的,就是这样。干杯:)
斯蒂芬·赖希


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.