Javaアプリケーション永遠のライバル、「OutOfMemoryError」(以下OOME)。
油断すると簡単に出るもので一見見落としがちなんですが、Exception(例外)ではなくエラーなんですよね。
Javadoc によると、Errorは「絶対に起きてはならない異常な状態である」だそうです。
OutOfMemoryErrorが発生した時点で JVM の中はいっぱいいっぱいになっており、状況は不定です。たとえそれが何らかの処理中であっても、その処理が正しいデータを出力する保証はなく、ただちに停止するべきであると考えられます。
ということで、OOMEが出たら再起動するようにしてみます。
今回は Windows 環境を対象としています。Linuxの場合、再起動用のコマンドなどが異なりますのでご注意ください。
再起動用バッチを作成する
まず、再起動を行うためのバッチを作成します。
たとえば、次のようなバッチファイルです。
TASKKILL /IM DataSpiderServer.exe /T
cmd /c start DataSpiderServer.exe
exit
TASKKILLコマンドで「DataSpiderServer.exe」のプロセスをkillします。
その後、DataSpiderServer.exe を実行します。
OutOfMemoryError発生時には、DataSpiderServerの状態は不定となり、終了コマンドを受け付けられないケースも考えられます。
そのため、Shutdown.exe ではなく TASKKILLコマンドを使います。
Windowsサービスに登録している場合は次のようなバッチファイルでも良いでしょう。
net stop "DataSpiderServer"
net start "DataSpiderServer"
バッチファイル単体で再起動が行えることを確認します。
コマンドによっては管理者権限が必要な場合もありますので、権限には注意してください。
作成したバッチファイルは $DATASPIDER_HOME/server/bin に配置しておきます。
名前はなんでも良いですが、今回は reboot.bat とします。
OnOutOfMemoryErrorオプションを使う
JVMのオプションである -XX:OnOutOfMemoryError
を利用します。
[http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html:title]
-XX:OnOutOfMemoryError
オプションはOutOfMemoryError発生時に指定したコマンドを実行するオプションです。
これに再起動コマンドを設定しておくことでOutOfMemoryError発生時に再起動が可能です。
-XX:OnOutOfMemoryError を設定する。
DataSpiderでは、$DATASPIDER_HOME/server/DataSpiderServer.lax の lax.nl.java.option.additional
にJVM引数を設定できます。
lax.nl.java.option.additional に次の引数を追加します。
-XX:OnOutOfMemoryError="cmd /c start reboot.bat"
単にreboot.batで良いんじゃないかと思うんですが、taskkillコマンドで自分自身をkillすることはできないため、startコマンドでjava.exeとreboot.batのプロセスを分けてからkillします。
サービスの再起動コマンドならreboot.batのみでいける可能性もあります。
設定できたら再起動確認する
- DataSpiderServerのヒープを128MB程度にして、OutOfMemoryErrorが発生しやすい状況を作ります。
- DataSpiderServerとStudioを起動して、サイズの大きいファイルを読み取るスクリプトを作成します。
- スクリプトを通常実行(ショートカットキー Ctrl+F5) で実行します。
- ファイルサイズが大きければ実行中に OutOfMemoryError が発生します。そのタイミングで設定したバッチファイルが実行され、DataSpiderServer が再起動されれば設定成功です。