【问题标题】:Track native memory usage from Java?从 Java 跟踪本机内存使用情况?
【发布时间】:2017-02-14 15:33:14
【问题描述】:

有什么方法可以记录 Java 的本机内存使用情况,即直接记录本机内存或进程使用的总内存(例如,询问操作系统)?

我想在幕后的用户机器上运行它,所以 NativeMemoryTracking 命令行工具并不是最吸引人的选项。我已经记录了空闲/最大/总堆大小。

背景:我的软件的用户报告了一个异常(如下),我不知道为什么。我的程序确实使用了 SWIG 的本机代码,但它是一个简单的 API,我认为它没有内存泄漏,并且不在堆栈跟踪中(或在错误之前立即运行)。我的日志表明发生错误时有足够的堆空间可用。所以我真的不知道如何追踪它。

java.lang.OutOfMemoryError: null
    at java.io.RandomAccessFile.writeBytes0(Native Method) ~[na:1.7.0_45]
    at java.io.RandomAccessFile.writeBytes(Unknown Source) ~[na:1.7.0_45]
    at java.io.RandomAccessFile.write(Unknown Source) ~[na:1.7.0_45]

错误发生在 Windows(7 或 10)(?)上,在 webstart 中,配置了以下参数:

<java href="http://java.sun.com/products/autodl/j2se" initial-heap-size="768m" java-vm-args="" max-heap-size="900m" version="1.7+"/>

【问题讨论】:

  • 问题发生在什么操作系统上?你能确定机器的虚拟机设置是如何配置的吗?内存分配失败的原因有很多,如果没有这些数据,甚至很难确定可能的原因,更不用说实际原因了。
  • @AndrewHenle 我已将这些详细信息添加到帖子中。

标签: java memory java-native-interface swig


【解决方案1】:

如果您想在您的特定方法或代码行上跟踪 JVM 内存,您可以使用 Runtime API。

    Runtime runtime = Runtime.getRuntime();
    NumberFormat format = NumberFormat.getInstance();

    long maxMemory = runtime.maxMemory();
    long allocatedMemory = runtime.totalMemory();
    long freeMemory = runtime.freeMemory();

System.out.println("free memory: " + format.format(freeMemory / 1024));
System.out.println("allocated memory: " + format.format(allocatedMemory / 1024));
System.out.println("max memory: " + format.format(maxMemory / 1024));
System.out.println("total free memory: " + format.format((freeMemory + (maxMemory - allocatedMemory)) / 1024));

【讨论】:

  • 我的问题是如何跟踪未在堆上分配的本机内存,因此这些方法无法跟踪。
  • 嗨@amos..不确定,但这篇文章可以帮助你,不确定你是否经历过这个。 stackoverflow.com/questions/2756798/java-native-memory-usage
  • 是的,我确实找到了。但是,我的目标是被动跟踪此信息,因此我不希望我的生产部署具有随机内存调试标志。
【解决方案2】:

我最终使用了this 代码,该代码向操作系统询问 RSS 和峰值内存使用情况。由于我已经设置了 SWIG 模块,因此添加起来很简单。代码可能不是线程安全的,因为我在测试时遇到了随机 malloc 异常,这意味着我不确定是否要将它保留在那里。

我真的很惊讶 JVM 没有提供一种方法来做到这一点。请有人告诉我是否有办法。

【讨论】:

    【解决方案3】:

    这是一段代码,它将字符串设置为等于使用的内存量(mb)/总内存量(mb),然后您可以使用它来记录您想要的任何内容!

    Runtime instance = Runtime.getRuntime();
    String mem = "Memory Used: "+ (instance.totalMemory() - instance.freeMemory()) / mb +"MB ("+
       (int)((instance.totalMemory() - instance.freeMemory())*1.0/instance.totalMemory()*100.0)+"%)"
    

    【讨论】:

      【解决方案4】:
      public final void writeBytes(String s) throws IOException {
          int len = s.length();
          byte[] b = new byte[len];
          s.getBytes(0, len, b, 0);
          writeBytes(b, 0, len);
      }
      

      查看源代码,足够大的字符串可能会导致内存不足错误。我怀疑你的堆日志是在这之前完成的,这解释了你看到的可用堆空间。我建议您验证是否是这种情况,如果是,请限制字符串大小和/或增加堆大小。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-02-14
        • 1970-01-01
        • 2011-05-16
        • 2013-01-14
        • 2011-01-18
        • 1970-01-01
        • 1970-01-01
        • 2017-06-17
        相关资源
        最近更新 更多