Pivotal Knowledge Base

关注

native内存故障分析

适用于

GemFire 6 及之后的版本

目的

Java应用程序虚拟机(VM)会将thread stack分配在native内存中。native内存位于堆内存之外。因此-Xms和-Xmx VM参数对其无效。-Xss参数是用于决定thread stack的大小。其默认值取决于操作系统和VM版本。一个应用程序能通过分配线程耗尽native heap,而同时仍有大量可用内存存在于VM heap中。

 

故障问题

发现native内存问题的办法之一是确认Gemfire或其他应用程序是不是抛出‘unable to create new native thread’的OutOfMemoryError。错误信息中必须包含‘unable to create new native thread’而不是‘Java heap space’消息。通过Heap Memory 问题页面可以看到具体原因。示例如下:

[severe 2008/09/29 10:56:12.919 EDT <Message Dispatcher for 127.0.0.1:2879> tid=0x56f]
Uncaught exception in thread <Message Dispatcher for 127.0.0.1:2879>
Caused by: java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:597)
Another way to check whether there is a native memory issue is to use either the gemfire stats command or vsd to display the number of threads contained in a given GemFire statistics archive. The vmStats category shows the number of threads in the VM at any time.

gemfire stats 命令

使用gemfire stats 命令来显示包含在指定GemFire statistics文件中的线程值,如下:

$ gemfire stats :VMStats.threads -archive=stats.gfs
[info] Found 1 match for ":VMStats.threads"
vmStats, 5112, VMStats: "2008/09/29 09:37:01.430 EDT" samples=4323
threads threads: samples=4323 min=37 max=127 average=83.2 stddev=6.93

Thread Dump

通过对运行中的VM使用kill -3 <pid>命令可以获得所有存在线程的dump信息。该命令不会关闭VM本身。而是发出信号让VM收集其所有线程的dump。示例如下:

[severe 2009/02/20 21:13:10.024 UTC libgemfire.so nid=0x40a18940] SIGQUIT received, dumping threads 
Full thread dump Java HotSpot(TM) 64-Bit Server VM (1.5.0_16-b02 mixed mode):
"Pooled Message Processor548" daemon prio=1 tid=0x00 nid=0x197d in Object.wait()
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:432)
...

"ServerConnection on port 42400 Thread 262" prio=1 tid=0x00 nid=0x1829 in Object.wait()
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:432)
...

"P2P message reader for server(32508):35047/56260 SHARED=false ORDERED=true" daemon prio=1 tid=0x00 nid=0x1800 runnable
at sun.nio.ch.FileDispatcher.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:21)
...

解决方案

简单来说,native内存是机器总物理内存与所有VM的heap内存之间的差值。事实上native内存更小,因为操作系统本身也会占用一部分内存。综上考虑,消除native内存问题有如下几个办法:

  1. 通过-Xss减小VM的thread stack size。比如-Xss256m 或者 -Xss384m应足以应对通常情况。
  2. 使用-Xmx减少VM的最大堆内存,这样可以使得剩余的总物理内存增大。
  3. 如果发生了连接泄露的问题,上面的办法只能推迟问题的发生。如果连接数持续增长,重要的是找到根本原因。如果使用了不支持特定版本Gemfire的Hyperic可能导致连接数持续增长。
  4. 增加总物理内存。

评论

由 Zendesk 提供技术支持