【问题标题】:How to get VM arguments from inside of Java application?如何从 Java 应用程序内部获取 VM 参数?
【发布时间】:2010-12-02 05:30:40
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: java jvm jvm-arguments


    【解决方案1】:

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

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

    value=System.getProperty("name");
    

    获取该值

    【讨论】:

    • 我不能用这个来获取-Xdebug
    • 不知道为什么这个答案如此受欢迎,它只检索应用程序参数(用 -D 指定),而不是 VM 参数(用 -X 指定的那些)。这个问题专门针对 -X 参数。
    • 我来到这里是因为我相信 -Dname=value 类型的参数是 JVM 参数,并且与 -X 参数没有本质区别。实际上,它们都被传递给 java 而不是命令行中的应用程序,作为示例,在 maven 中,您可以将两者都传递为-Drun.jvmArguments=...。我相信这就是它被赞成的原因。
    • 这根本无法满足原始海报的需求。
    • 可能是!但是在搜索“如何在代码中读取 VM 选项”时,它会在顶部搜索,这就是它相关的原因)
    【解决方案2】:

    使用此代码,您可以获得 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());
    • 如果您保证在 Oracle 的 JVM 上运行并且拥有解析参数的代码可能有用。
    • @Vulcan 那没有得到 VM 参数。它包含主类名和主方法的 args 数组。
    • @dacongy 我从来没有暗示VM参数位于sun.java.command系统属性中;我说过该属性可用于获取主类名(尽管我没有提到,正如@laz 指出的那样,该属性仅存在于 Oracle 的 JVM 上)。
    【解决方案3】:

    我发现 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&lt;String&gt; 中的参数,可以缩短。

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

    【讨论】:

    • 是的,刚刚做到了。干杯:)
    【解决方案4】:

    我没有尝试专门获取 VM 设置,但是 JMX 实用程序中提供了大量信息,特别是 MXBean 实用程序。这将是我开始的地方。希望您能在那里找到对您有所帮助的东西。

    sun 网站上有一堆技术:

    http://java.sun.com/javase/6/docs/technotes/guides/management/mxbeans.html

    【讨论】:

      【解决方案5】:

      如果你想要你的java进程的整个命令行,你可以使用:JvmArguments.java (使用 JNA + /proc 的组合来涵盖大多数 unix 实现)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-11-13
        • 2012-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-12
        • 1970-01-01
        相关资源
        最近更新 更多