きどたかのブログ

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

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

ClassNotFoundは解析が簡単な問題のひとつです。
それはたとえWASのクラスであってもです。
ClassNotFoundの問題を自力で調べられないようではまだまだお子様でしょう。


まず初めに、どのクラスが見つからないかがメッセージで出てるでしょう。
次にやることは、どのJarに含まれているかを知ることです。
簡易的にeclipse使って調べてしまいます。
この方法は正しい調べ方ではありませんが、おおむね当たります。


どのJarに含まれているか分かった後にすることは、
そのJarにクラスパスが通っているかを確認することです。
一言でクラスパスと言ってますが、クラスパスとはひとつではありません。


クラスパスが通っていることの確認は、クラスローダー・ビューアでもいいです。
ただ、自分はz/OSの場合、クラスローダー・ビューアは参考程度にとどめます。
あれはおそらくはSRの情報でしょうけど、どのSRの情報かいまいち自信が持てない。
CRやCRAの問題には使えなさそうだし。
javacoreを見るのでもいいです。
他に構成ファイルから知る方法があります。
ほとんどJOBLOGに出ていますが、とりあえず構成ファイルから調べるのがいいですかね。
ClassNotFoundの多くは人災ですから、構成ファイルを疑うのから始めるのがいい。


今回はDB2のデータストア・ヘルパー(WASの持ってるやつ)が見つからないという問題でした。


はい、ここで初心者と経験者の分岐点です。
経験者は、どのクラスローダーがそれを読むべきかを把握してます。
クラスパスがひとつではないとはこれのことです。
もしくはすぐに正常時はどうなのかをクラスローダー・ビューアなどで確認します。
当然ながらクラスローダーの階層構造と委譲関係をしっかり把握してないといけません。
このクラス/Jarの場合は、WebSphere Extensions Class Loaderが読みます。


さて、クラスローダーというのはそれぞれクラスを探すときにその守備範囲があります。
WebSphere Extensions Class Loaderは-Dws.ext.dirsに置いてあるものを読み込みます。
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=compass&product=was-nd-dist&topic=crun_classload
ちなみにws.ext.dirsの値はJOBLOGにも出てました。


念のため、ws.ext.dirsの値を調べる方法として次のファイルも目を通します。
servant.jvm.options
server.xml
WebSphere変数 WAS_SERVER_ONLY_default_jvm_options (node-scope)
これはServantの場合ですね、CRとかもほぼ同じです。


今回の場合、自分は初めにservant.jvm.optionsを見ました。
それは最終的にはこのファイルが使われるはずだからです。
すると-Dws.ext.dirsが空っぽになってるではありませんか。異常です。
ここまで来るのにそんなには時間はかかってません。
むしろ送られてきた構成ファイルがEBCDICだったんで、
それをコンバートするのに書いたJavaのコードのほうにこそ時間がかかってます。
次にserver.xmlで確認してみました。おやおや、こちらは指定がある。
指定があるのに、optionsに反映されてないという摩訶不思議。


process definitionからws.ext.dirsの指定をしたとしても、
通常はWAS_SERVER_ONLY_default_jvm_optionsとマージされて使われるようですが、なぜかブランク。
(このへんの確認を実機で数回検証)


どうも存在しないWebSphere変数を使ってws.ext.dirsを定義しているのが関係してそうだ。
見慣れないWebSphere変数があるから初見で怪しいと思ってました。
その場合にどうなるかを自分の環境で実験してみたところ見事にブランクになりました。


クラスパス通ってないんだもん、そりゃあ見つからないでしょ。


WebSphere変数をミスると、たまにこういうのに遭遇するので、チェックは慎重に。
今回のはクラスローダーの委譲関係やら共用ライブラリとか調べるような類じゃなかったので楽ですね。


せめて存在しないWebSphere変数に出くわしたらWarningとか出ないのかな?
もしかして出てたのに見落としたか?