In my asset-converter app, I toggled MemoryDebugState (from SiO2) with
includeDirectMem enabled to view direct memory usage of the app but it looks like native memory tracking does not work. It displays “100% (0.09/0.09 mb)” and does to change. Internally it uses
com.jme3.util.MemoryUtils to grab direct memory usage and total capacity.
If I try using
BufferUtils.printCurrentDirectMemory() I get the correct numbers. (I need to enable tracking with
Seems there is an issue with MemoryUtils.
And just in case I am using Linux and Java 17.
Somewhere along the way (at least as late as Java 8), Java stopped keeping a separate direct memory pool… there is literally no way that I’ve found to query it and I’ve been down every mbean rabbit hold in jconsole. At best, the “max” of the direct pool is whatever is in use at any given time and even that doesn’t seem to work in later Javas. The command line setting to set max direct heap appears to do nothing at all.
When you turn on setTrackDirectMemoryEnabled() on BufferUtils then it counts the memory that BufferUtils has created but this could be a very different number than the actual direct memory used.
Bottom line: there is no reliable way that I’ve found to get this information anymore and everything I’ve seen hints that it’s likely not necessary to care anymore, either.
If I switch to PrimitiveBufferAllocator then MemoryDebugState will display direct memory usage correctly, though the total capacity value still seems off but the memory usage works fine at least. It seems JVM can only track direct memory allocated using NIO ByteBuffer (
java.nio.ByteBuffer.allocateDirect()) and does not track native memory allocated by
org.lwjgl.system.MemoryUtil which is used in LwjglBufferAllocator.
Aside from that, I also noticed the limit passed by the
MaxDirectMemorySize VM arg is never respected when using LwjglBufferAllocator and direct memory usage will continue to grow beyond the limit which could be another reason that JVM does not track the memory allocated by LwjglBufferAllocator.
With Java 6 or 7 (I don’t remember) it was super critical to track direct heap usage because it was managed totally separately from the main heap. On its own it would not trigger a garbage collection and so it was important to keep your max heap and max direct memory tuned carefully for the app.
I find in Java 8 and beyond that this is unnecessary… and believe me that I create a LOT of buffers and throw them away. I have one main memory percentage that I track and that’s it. The only times I’ve ever seen OOM errors is when that percentage indicates that I’m nearing 100%… and generally this is a memory leak in my app.
I haven’t seen an OOM error related to direct heap in many many years.
Edit: in Java 6 (old Mythruna) it was also required that I free the buffers myself or they would hang around too long. I no longer do this either.