-XX:未从_JAVA_OPTIONS中获取NativeMemoryTracking

时间:2017-01-02 17:01:12

标签: java

我无法通过_JAVA_OPTIONS获取NMT设置。我的环境是kubernetes集群上的Docker容器,_JAVA_OPTIONS包含启用NMT的标志(见下文)。

为了证明我已经创建了一个小型演示类Hello,它每秒打印一行。

a)我在没有命令行参数的情况下运行Hello

[root@ticc-services-abo-3354894200-5fixb tmp]# echo $_JAVA_OPTIONS
-Xmx512m -Xms512m -XX:NativeMemoryTracking=summary
[root@ticc-services-abo-3354894200-5fixb tmp]# java Hello
Picked up _JAVA_OPTIONS: -Xmx512m -Xms512m -XX:NativeMemoryTracking=summary
hello 0
hello 1
...

在另一个控制台上,我尝试获取NTM摘要,但无法访问:

[root@ticc-services-abo-3354894200-5fixb /]# jcmd
Picked up _JAVA_OPTIONS: -Xmx512m -Xms512m -XX:NativeMemoryTracking=summary
1 /opt/abo.jar
740 Hello
766 sun.tools.jcmd.JCmd
[root@ticc-services-abo-3354894200-5fixb /]# jcmd 740 VM.native_memory
Picked up _JAVA_OPTIONS: -Xmx512m -Xms512m -XX:NativeMemoryTracking=summary
740:
Native memory tracking is not enabled

b)现在我直接在命令行上设置NMT标志:

[root@ticc-services-abo-3354894200-5fixb tmp]# java -XX:NativeMemoryTracking=summary Hello
Picked up _JAVA_OPTIONS: -Xmx512m -Xms512m -XX:NativeMemoryTracking=summary
hello 0
hello 1
...

和NMT的工作原理:

[root@ticc-services-abo-3354894200-5fixb tmp]# jcmd
Picked up _JAVA_OPTIONS: -Xmx512m -Xms512m -XX:NativeMemoryTracking=summary
1 /opt/abo.jar
834 Hello
846 sun.tools.jcmd.JCmd
[root@ticc-services-abo-3354894200-5fixb tmp]# jcmd 834 VM.native_memory summary
Picked up _JAVA_OPTIONS: -Xmx512m -Xms512m -XX:NativeMemoryTracking=summary
834:

Native Memory Tracking:

Total: reserved=1873866KB, committed=574898KB
-                 Java Heap (reserved=524288KB, committed=524288KB)
                        (mmap: reserved=524288KB, committed=524288KB)
...

修改Hello以打印其堆总数和最大值后,我们看到-Xms-Xmx被拾取但NMT标志没有,因为Java没有抱怨坏的NMT标志:

[root@ticc-services-abo-3354894200-5fixb tmp]# echo $_JAVA_OPTIONS
-Xmx256m -Xms128m -XX:NativeMemoryTracking=summary_FOO
[root@ticc-services-abo-3354894200-5fixb tmp]# java Hello
Picked up _JAVA_OPTIONS: -Xmx256m -Xms128m  -XX:NativeMemoryTracking=summary_FOO
heap: total=128974848, max=239075328
hello 0
hello 1
hello 2

这是我的环境:

[root@ticc-services-abo-3354894200-5fixb /]# uname -a
Linux ticc-services-abo-3354894200-5fixb 4.7.3-coreos-r2 #1 SMP Tue Nov 1 01:38:43 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
[root@ticc-services-abo-3354894200-5fixb /]# java -version
Picked up _JAVA_OPTIONS: -Xmx512m -Xms512m -XX:NativeMemoryTracking=summary
java version "1.8.0_91"
Java(TM) SE Runtime Environment (build 1.8.0_91-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)

这看起来很奇怪,所以任何提示或想法都非常欢迎。

1 个答案:

答案 0 :(得分:0)

我相信您的计算机中存在的环境变量与启动该Java进程的VM参数之间存在混淆。

您可以将其命名为 _JAVA_OPTIONS,JAVA_OPTIONS,MY_STARTUP_OPTION 或任何其他名称,该名称没有什么特别的,它不是Java进程的保留字。

您的Java代码正在打印出该变量的值的事实也使其与众不同:

  System.out.println("Picked up JAVA_OPTIONS: "+System.getenv("_JAVA_OPTIONS"));
  System.out.println("Picked up JAVA_OPTIONS: "+System.getenv("JAVA_OPTIONS"));

对于此Java进程,它只是另一个常见的env变量。 这里重要的是要知道该变量是否用于启动您的过程,并根据本示例中显示的步骤顺序,答案是否定的。

如果希望使该变量用于启动该Java进程,则应使用:

java $JAVA_OPTIONS Hello

java $_JAVA_OPTIONS Hello

此外,要打印出此Java进程的VM参数,可以使用:

ManagementFactory.getRuntimeMXBean().getInputArguments();

这是完整的Java代码

import java.lang.management.ManagementFactory;
import java.util.List;

public class Hello {

    public static void main(String[] args) {
        int i = 0;
        System.out.println("Picked up JAVA_OPTIONS: "+System.getenv("JAVA_OPTIONS"));
        System.out.println("VMArguments: "+Hello.vmArguments().toString());
        try {

            while (true) {
                System.out.println("hello " + (i++));
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            System.out.println("Good bye");
            e.printStackTrace();
        }

    }

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

}

还有一个执行示例:

C:\Hello\bin>echo %JAVA_OPTIONS%
-Xmx512m -Xms512m -XX:NativeMemoryTracking=summary

C:\Hello\bin>echo %MY_STARTUP_OPTION%
-XX:NativeMemoryTracking=detail

C:\Hello\bin>java %MY_STARTUP_OPTION% Hello
Picked up JAVA_OPTIONS: -Xmx512m -Xms512m -XX:NativeMemoryTracking=summary
VMArguments: [-XX:NativeMemoryTracking=detail]
hello 0

C:\Hello\bin>java %JAVA_OPTIONS% Hello
Picked up JAVA_OPTIONS: -Xmx512m -Xms512m -XX:NativeMemoryTracking=summary
VMArguments: [-Xmx512m, -Xms512m, -XX:NativeMemoryTracking=summary]
hello 0

在另一个终端上,您可以使用 $ JAVA_HOME / bin / jps ps -fea | grep java 。 这是Windows中的示例:

C:\Users\MyUser>jps -lv
5644 Hello -Xmx512m -Xms512m -XX:NativeMemoryTracking=summary

我希望称为JAVA_OPTIONS的变量或任何env变量与VM参数之间的区别是明确的。

回到最初的问题我不确定,但是Kubernetes似乎使用了 JAVA_OPTS 环境变量。选中https://dev.to/sandrogiacom/kubernetes-for-java-developers-debug-application-4l1a

关于NMT的选项,官方文档中提到了“摘要”和“详细信息”。

参考:https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/tooldescr007.html

希望有帮助!