2016年02月07日

OutOfMemoryError(〜 unable to create new native thread 〜)が発生したときにフォローした内容について

(32bitOS上の)Javaプロセスにて2000個のスレッドを起動できないということで、フォローした内容を展開しておきます。

トラブル内容
・1000個のスレッドは起動できた
・1500個のスレッドも起動できた
・2000個のスレッドは起動できなかった
・OutOfMemoryErrorが発生した
 ( "java.lang.OutOfMemoryError: unable to create new native thread 〜 (Native Method) 〜" )

対応内容
まず、単純にJavaヒープ(-Xms、-Xmx)をアップしたところ、起動できたスレッド数が逆に減少したため、
また、スタックトレースに"(Native Method)"が含まれていたため、
Cヒープの枯渇を疑った。
(通常、Cヒープの枯渇の場合は "java.lang.OutOfMemoryError: requested … bytes …" 。)

上記につき、(各スレッド毎の)スレッドスタック(-Xss)をダウンすること(+Javaヒープを必要最小限にすること)で2000個のスレッドを起動できた。
例) # java -Xss128k -Xms512m -Xmx512m xxxxx.Xxxxx

(余談)
もし、解決できなかった場合は、64bitOSに変更するか、Javaプロセスを多重化する(OSのメモリに余裕がある場合のみ)、などが考えられる。

おまけ@
各プロセスに割り当てられる仮想メモリ(アドレス空間)の最大値は
32bitOS : 2GB (4GB÷(ユーザープロセス+カーネルプロセス)=2GB)
64bitOS : 8TB
である。
また、Javaプロセスは仮想メモリを 主にJavaヒープ領域、Cヒープ領域、スレッドスタック領域 として利用する。
このうち、Javaヒープ領域には(起動オプションで)制限をかけることができるが、
Cヒープ領域、スレッドスタック領域※ には(起動オプションで)制限をかけることができない。
そのため、Javaヒープ領域をアップし過ぎると、Cヒープ領域を減少させてしまい、その結果、生成できるスレッド数が減少することになる。
※正確には、(各スレッド毎の)スレッドスタックは指定できるが、スレッド数は指定できないため = 制限をかけることができない。

おまけA
# java -XX:+PrintFlagsFinal
で、起動オプションのデフォルト値を確認することができる。
-Xss : ThreadStackSize
-Xms : InitialHeapSize
-Xmx : MaxHeapSize

posted by red at 15:53| Comment(0) | TrackBack(0) | Java | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

※ブログオーナーが承認したコメントのみ表示されます。

この記事へのトラックバック