java 的本机内存跟踪输出的 "other" 部分包含哪些内容?

What goes into the "other" section of java's native memory tracking output?

我正在尝试调试内存使用率较高的 Java 应用程序。使用本机内存跟踪,我发现名为“其他”的部分正在使用大量内存。我似乎无法在网上找到任何关于可能存储在这里的内容、可能导致它过高的原因或如何进一步调试它的任何信息。在这些方面的任何帮助将不胜感激。作为参考,这是我从 jcmd 获得的输出:

Total: reserved=49GB, committed=48GB
-                 Java Heap (reserved=32GB, committed=32GB)
                            (mmap: reserved=32GB, committed=32GB)

-                    Thread (reserved=1GB, committed=0GB)
                            (thread #1291)
                            (stack: reserved=1GB, committed=0GB)

-                        GC (reserved=2GB, committed=2GB)
                            (mmap: reserved=1GB, committed=1GB)

-                     Other (reserved=14GB, committed=14GB)
                            (malloc=14GB #1520)

你应该说你使用 java-11(或更高),因为以前它被称为 Internal(它包含更多)。

这是通过 ByteBuffer::allocateDirect 进行的每一次分配。

NMT 报告的

Other 部分计算应用程序通过 Direct ByteBuffers 或立即通过 Unsafe.allocateMemory 分配的堆外内存。 ByteBuffer.allocateDirect 在后台调用 Unsafe.allocateMemory

您可以通过 JMX 监控 Direct ByteBuffer 的数量和它们占用的总内存 - 查找 BufferPool MBean:

Async-profiler 可以帮助找到分配堆外内存的位置。 运行

profiler.sh -d <duration> -e jdk.internal.misc.Unsafe.allocateMemory -f profile.html <pid>

这将创建一个火焰图,显示调用 Unsafe.allocateMemory(包括 ByteBuffer.allocateDirect)的所有位置的堆栈跟踪:

有关 ByteBuffers 及其与堆外内存使用的关系的更多信息,请参阅 this presentation