Pivotal Knowledge Base

フォローする

ネイティブメモリにおける問題

適用範囲

GemFire 6 以降

目的

Java アプリケーション VM は、ネイティブメモリにスレッドスタック領域を割り当てる。ネイティブメモリはヒープ外の領域である。したがって、-Xms や -Xmx といった VM 引数の設定は効果がない。スレッドスタックサイズを決定するには、-Xss VM 引数が使用される。デフォルト値は、OS や VM のバージョンに依存する。アプリケーションにおいて、十分な空きヒープ領域あるのに、スレッド割り当てによりネイティブヒープが枯渇することはあり得る。

問題

ネイティブメモリ問題の発生を知る一つの方法は、GemFire やアプリケーションによって、'unable to create new native thread' というメッセージとともに OutOfMemoeryError のスローを確認することである。当該エラーは 'unable to create new native thread' というメッセージが付与されており、'Java heap space' というメッセージは付与されていない。ヒープメモリに関する問題の詳細はナレッジベース記事「ヒープメモリにおける問題へのトラブルシューティング」を参照されたい。ネイティブメモリ問題に対するメッセージ出力の一例を以下に示す。

[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 統計情報ファイルに含まれる VMStats スレッドの値を表示することがあげられる。

$ 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

スレッドダンプ

稼働中の仮想マシンに対して kill -3 <プロセス ID> を実行することにより、全ての稼働中のスレッドをダンプすることができる。これは、仮想マシン自体を停止するものではない。代わりに、全ての稼働中スレッドにおける現在の状態をダンプするようシグナルを送るものである。出力例は以下である。

[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)
...

解決策

端的に言うと、ネイティブメモリのサイズは、マシン上の物理 RAM 容量から仮想マシンのヒープサイズを引いた差分である。オペレーティングシステムも物理 RAM の一部を使用しているので、実際にはいくぶん少ないであろう。この前提の元、ネイティブメモリ問題を解決するいくつかの方法を以下に列挙する。

  1. -Xss を用いて仮想マシンのスレッドスタックサイズを減らす。-Xss256m あるいは、-Xss384m 程度で十分と考えられる。
  2. -Xmx を用いて仮想マシンの最大ヒープサイズを減らす。これにより、物理 RAM 容量とヒープサイズの差分が増え、結果ネイティブメモリのサイズが増える。
  3. コネクションリークが発生しているような場合は、上述の対策を講じても問題発生までの時間稼ぎにしかならない。例えば、そのようなコネクションは、GemFire でサポートされていないバージョンの Hyperic を用いた場合に生成されたという事例がある。
  4. マシンに RAM を追加する。

コメント

Powered by Zendesk