有什么方法可以记录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]
在webstart中使用以下参数配置的Windows(7或10)(?)上发生错误:
<java href="http://java.sun.com/products/autodl/j2se" initial-heap-size="768m" java-vm-args="" max-heap-size="900m" version="1.7+"/>
答案 0 :(得分:2)
如果您想要在某个方法或代码行上追踪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));
答案 1 :(得分:1)
我最终使用了this代码,要求操作系统提供RSS和峰值内存使用情况。由于我已经设置了SWIG模块,因此我可以直接添加。代码可能不是线程安全的,因为我在测试时遇到了一个随机的malloc异常,这意味着我不确定是否要将它保留在那里。
我真的很惊讶JVM没有提供这样做的方法。如果有办法,请有人告诉我。
答案 2 :(得分:0)
下面是一段代码,它将字符串设置为等于使用的内存量(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)+"%)"
答案 3 :(得分:-1)
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);
}
查看源代码,足够大的String可能会导致内存不足错误。我怀疑你的堆日志是在这之前完成的,这解释了你看到的免费堆空间。我建议您验证是否是这种情况,如果是,请限制字符串大小和/或增加堆大小。