原视频链接:不存在的网站,翻译此视频并发布已获得原作者同意。
Java进程的内存占用[译] Part 4 - AndreiPangin
JVM运行时 - JIT 编译器
线程栈(Thread Stack)也会消耗本地内存,所以NMT报告中也包含了专用于线程的内存,这上面的数字看起来吓人,例如500个线程用了500M多内存。
这是因为默认线程栈大小是1M,可以通过-Xss选项调整。实际上没那么吓人,毕竟操作系统分配物理内存中的内存页是惰性的,线程栈的顶部其实是没用的,所以其实没用到物理内存,除非特殊情况。为了避免定义上的混乱,JDK11 的NMT报告中,将计算常驻内存中的线程栈大小,而不是提交(committed)的大小,所以现在的话,平均一个线程会消耗50~200K的内存,并不是那么离谱。
本地内存 - Symbols
Symbols是另外一个有意思的NMT报告部分,它统计了两个JVM内部哈希表所消耗的内存:Symbol表 和 String表。Symbol表包含了名称、签名,String表包含了字符串内部池(Interned string)的引用。
如果你的应用创建了很多Interned strings,这将会导致不稳定(OutOfMemory ),最近的JDK其他有用的Java Command,本例中,一千万Interned strings使用了超过700M内存。如果遇到了有关string表和symbol表的问题,可以用jcmd PID VM.stringtable | VM.symbolstable
命令,导出对应表的内容,有兴趣的话,可以看下我在Stack Overflow中的回答:如何打印Symbol表的内容。