読者です 読者をやめる 読者になる 読者になる

きどたかのブログ

いつか誰かがこのブログからトラブルを解決しますように。

今日のOOM解析(難易度 初級)

OutOfMemoryErrorがきた。
まずGCログを見る。
Javaヒープ足りてるな。
じゃあネイティブが怪しいんだろ。
それにしてもafの他にsys出てるけど何でSystem.gc()とか使ってるんだろう。


MQとDB2の設定をわかる範囲でかき集める。
一般的にネイティブは、Javaのクラス情報とかJITとか、
あとはMQのBINDING MODEとかDB2のtype2接続なんかで使われているので、
それと思われる情報を揃えていく。
MQはBINDING MODEじゃないっぽい。
DB2はtype2とtype4のようだ。


JOBLOGでMQ Provider Version確認。
JCLのSTEPLIBにはDB2のみ。MQのはない。
まあ、LINKLSTかも知れんので参考までに。データセット名からはバージョン推測出来ず。
javacoreからDB2のドライバーパス、それでバージョンも判明。
JOBLOGにドライバーバージョンもある。
type4のログも出てた。
ある例外のスタックトレースからtype2も使ってると判明。
JOBLOGからREGION=0M無制限。
javacoreからMQ_INSTALL_ROOTを発見、だけどWAS V7ではこれでネイティブライブラリは読まないので無視。


javacoreからRLIMIT関連を収集。
んー、潤沢。
てか無制限と言っていい。


本当にDB2かな?
そんなにネイティブ使うか?
参照圧縮もついてるし、2GBバーも気にしてたけど、RLIMIT_ASからして、2GBバーは関係なしだろ。
ヒープダンプでとりあえずコネクションやステートメントを数えてみる。
おやまあ少ない。
やっぱり違う気がするぞ。


OOMのメッセージを読み直す。
なんかこれ見たことないんだよな。
スレッド作るのに失敗。
ATTACHマクロ調べてみようか。
ちょっと期待してた情報がなかった。残念。


んー、ググる
製品違うけどそれっぽいの見つかった。
http://www-01.ibm.com/support/docview.wss?uid=swg21396557


MAXTREADSに達したっぽいな。
この資料ではRACFでやるユーザー毎の制限を変更しているが、BPXPRMxxでの制限のほうも調べておく。
SETOMVSなんて普段叩かないなぁ。よしよし動的にいけるいける。
それにしてもなんでそんなにスレッドが必要?


ヒープダンプからスレッドアナリシスをしてみる。もちろんMemory Analyzerで。
やけに多いんだよなぁ。
javacoreでも同じように多く、waitしてる。
SRのスレッド数とは桁違い。
普通のWASだとなんのスレッドか推測出来る。
こいつはWASじゃないぞ、きっと。


javacoreをもっとじっくり見てみる。
スレッドをスタートしとるやつがいた。
MQのクラスだけど、アプリケーションから呼ばれてる。
ああ、これJOBLOGにも出てたやつだわ。
ふーむ、アプリケーションの問題だね。
com.ibm.mq.MQSimpleConnectionManagerはMQのコネクションを管理するクラスなんだが、
これを使うと裏で監視のスレッドが走るようだ。
com.ibm.mq.PoolScavenger、こいつ自体はスレッドではないが、こいつが監視するスレッドを動かす。
こちらのクラスはAPIとして公開されているクラスではないので直接動かすことはない。
スタックトレースでは、MQSimpleConnectionManager.setActive(int mode)でPoolScavengerがスレッドを動かしてたはず。


Using JMS connection pooling with WebSphere Application Server and WebSphere MQ, Part 2
http://www.ibm.com/developerworks/websphere/library/techarticles/0709_titheridge/0709_titheridge.html


com.ibm.mq.MQSimpleConnectionManagerのJavaDoc
http://publib.boulder.ibm.com/infocenter/wmqv7/v7r0/topic/com.ibm.mq.javadoc.doc/WMQJavaClasses/com/ibm/mq/MQSimpleConnectionManager.html


Connection pooling in WebSphere MQ classes for Java
http://publib.boulder.ibm.com/infocenter/wmqv7/v7r0/topic/com.ibm.mq.csqzaw.doc/ja11210_.htm


スレッドが徐々にリークというオチか。
com.ibm.mq.MQSimpleConnectionManagerが膨大な数、ヒープダンプから観測された。
プールするやつが何匹も必要ないだろ。
なんで接続ファクトリーをルックアップしてないんだよ。


このようにところどころミスリードしてしまったが、本物の原因に辿り着けたと思う。


「違うと思う」となる部分がたまにあるけど、こればかりは経験だ。
論理的には起こりうることだけど、甚だ怪しいと感じる。


この問題について、自分は2回誤った結論に向かっていた。
ネイティブメモリと、スレッド数。
しかし、これを否定したのが経験。
ただし、この誤った結論もまた経験から生み出されていたりもする。
やっぱり思い込みはたまに修正せんとな。
OOMでJavaヒープじゃなかったからネイティブという思い込み。
JMSは接続ファクトリーをルックアップして、WASからの設定でプールを管理してるという思い込み。
一番初めのJOBLOGのメッセージをちゃんと調査せずに進めたことと、
JOBLOGのスタックトレースでMQからスレッドを作りに行ってるので安心して、
ユーザーアプリケーションから動かされている点に気付かなかったことは、慢心があったと言わざるを得ない。


ほぼ解決したと思っててもいいだろう。