16

If I create a buffer via ByteBuffer.allocateDirect(), the memory exists outside of the Java heap. Is there a way to measure this kind of memory usage from my application in a cross-platform way similar to how I can measure Java heap usage with Runtime.totalMemory() and Runtime.freeMemory()?

martinez314
  • 12,162
  • 5
  • 36
  • 63

2 Answers2

15

You can use MXBeans to get the memory used by the direct byte buffers and mapped byte buffers:

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();
}

prints something like:

direct
122
memory used 456.1562509536743 MB
total capacity456.15625 MB

mapped
0
memory used 0.0 MB
total capacity0.0 MB

where toMB function is this:

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

However, I am not 100% sure if direct byte buffers are the only things that can live in the direct memory. Perhaps there are other things...

Ali Ok
  • 716
  • 1
  • 8
  • 23
2

You can use reflections to get Bits.reservedMemory on OpenJDK/HotSpot Java 7. There is no platform independent way and this only shows you the usage via ByteBuffer.allocateDirect() not any other way of allocating native memory.

An alternative is to parse /proc/{pid}/maps and exclude file mappings. This is an approximation of the virtual memory your process is using.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 7
    I was able to get the value with `sun.misc.SharedSecrets.getJavaNioAccess().getDirectBufferPool().getMemoryUsed()` and `sun.misc.VM.maxDirectMemory()`. Better or worse than reflection? – martinez314 Nov 20 '13 at 17:03
  • @whiskeyspider simpler than using reflection. – Peter Lawrey Nov 20 '13 at 19:34
  • 2
    Just a side note, `SharedSecrets` will not show you used memory if it is allocated via low-level `Unsafe.allocateMemory()`, in this case, you should either track/count allocated memory yourself or parse `/proc/{pid}/maps` as in the answer. – Zaur Guliyev Mar 09 '18 at 15:13
  • 1
    @ZaurGuliyev for more detail `/proc/self/smaps` which will even include how much memory is private and in memory vs on disk. – Peter Lawrey Mar 11 '18 at 15:47