有没有办法测量Java中的直接内存使用量?

whi*_*der 8 java memory nio

如果我通过创建缓冲区ByteBuffer.allocateDirect(),则内存存在于Java堆之外.有没有办法以跨平台的方式从我的应用程序中测量这种内存使用情况,类似于我如何使用Runtime.totalMemory()和测量Java堆使用情况Runtime.freeMemory()

Ali*_* Ok 6

您可以使用MXBeans获取直接字节缓冲区和映射字节缓冲区使用的内存:

List<BufferPoolMXBean> pools = ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class);
for (BufferPoolMXBean pool : pools) {
    System.out.println(pool.getName());
    System.out.println(pool.getCount());
    System.out.println("memory used " + toMB(pool.getMemoryUsed()));
    System.out.println("total capacity" + toMB(pool.getTotalCapacity()));
    System.out.println();
}
Run Code Online (Sandbox Code Playgroud)

打印类似:

direct
122
memory used 456.1562509536743 MB
total capacity456.15625 MB

mapped
0
memory used 0.0 MB
total capacity0.0 MB
Run Code Online (Sandbox Code Playgroud)

toMB函数在哪里:

private static String toMB(long init) {
    return (Long.valueOf(init).doubleValue() / (1024 * 1024)) + " MB";
}
Run Code Online (Sandbox Code Playgroud)

但是,我不是100%确定直接字节缓冲区是否是唯一可以存在于直接内存中的东西。也许还有其他事情...


Pet*_*rey 2

您可以使用反射来获取Bits.reservedMemoryOpenJDK/HotSpot Java 7。没有独立于平台的方式,这仅向您显示通过 ByteBuffer.allocateDirect() 的使用情况,而不是任何其他分配本机内存的方式。

另一种方法是解析/proc/{pid}/maps并排除文件映射。这是您的进程正在使用的虚拟内存的近似值。

  • 我能够通过 `sun.misc.SharedSecrets.getJavaNioAccess().getDirectBufferPool().getMemoryUsed()` 和 `sun.misc.VM.maxDirectMemory()` 获取值。比反思更好还是更差? (7认同)
  • 附带说明一下,如果通过低级 Unsafe.allocateMemory() 分配内存,那么 SharedSecrets 将不会显示已使用的内存,在这种情况下,您应该自己跟踪/计算分配的内存或解析 /proc/{ pid}/maps` 如答案所示。 (2认同)