0000000100000000 8K r-x-- /sw/.es-base/sparc/pkg/jdk-1.7.0_60/bin/sparcv9/java
0000000100100000 8K rwx-- /sw/.es-base/sparc/pkg/jdk-1.7.0_60/bin/sparcv9/java
0000000100102000 56K rwx-- [ heap ]
0000000100110000 2624K rwx-- [ heap ] <--- native Heap
00000001FB000000 24576K rw--- [ anon ] <--- Java Heap starts here
0000000200000000 1396736K rw--- [ anon ]
0000000600000000 700416K rw--- [ anon ]
这个问题可以通过-XX:HeapBaseMinAddress=n选项来解决,它能指定Java堆的起始地址。将它的设置成一个更高的地址将会为原生堆留出更多的空间。
关于如何诊断、排查和解决该问题,请参阅该文了解更详细的信息。
原生堆:诊断工具让我们看一下内存泄露的探查工具,它们能够帮助我们找到原生内存泄露的原因。
原生内存跟踪JVM有一个强大的特性叫做原生内存跟踪(Native Memory Tracking,NMT),它在JVM内部用来跟踪原生内存。需要注意的是,它无法跟踪JVM之外或原生库分配的内存。通过下面两个简单的步骤,我们就可以监控JVM的原生内存使用情况:
以启用NMT的方式启动进程。输出级别可以设置为“summary”或“detail”级别:
-XX:NativeMemoryTracking=summary
-XX:NativeMemoryTracking=detail
使用jcmd来获取原生内存使用的细节:
jcmd <pid> VM.native_memory
NMT输出的样例:
d:\tests>jcmd 90172 VM.native_memory 90172:
Native Memory Tracking:
Total: reserved=3431296KB, committed=2132244KB
- Java Heap (reserved=2017280KB, committed=2017280KB)
(mmap: reserved=2017280KB, committed=2017280KB)
- Class (reserved=1062088KB, committed=10184KB)
(classes #411)
(malloc=5320KB #190)
(mmap: reserved=1056768KB, committed=4864KB)
- Thread (reserved=15423KB, committed=15423KB)
(thread #16)
(stack: reserved=15360KB, committed=15360KB)
(malloc=45KB #81)
(arena=18KB #30)
- Code (reserved=249658KB, committed=2594KB)
(malloc=58KB #348)
(mmap: reserved=249600KB, committed=2536KB)
- GC (reserved=79628KB, committed=79544KB)
(malloc=5772KB #118)
(mmap: reserved=73856KB, committed=73772KB)
- Compiler (reserved=138KB, committed=138KB)
(malloc=8KB #41)
(arena=131KB #3)
- Internal (reserved=5380KB, committed=5380KB)
(malloc=5316KB #1357)
(mmap: reserved=64KB, committed=64KB)
- Symbol (reserved=1367KB, committed=1367KB)
(malloc=911KB #112)
(arena=456KB #1)
- Native Memory Tracking (reserved=118KB, committed=118KB)
(malloc=66KB #1040)
(tracking overhead=52KB)
- Arena Chunk (reserved=217KB, committed=217KB)
(malloc=217KB)
关于使用jcmd命令访问NMT数据的细节以及如何阅读它的输出,可以参见该文。
原生内存泄露探查工具