YmirとJavaRebelの連携

YmirではS2のHOT Deploy機能を使ってアプリケーションの再配備なしにコードの変更を動作中のアプリケーションにリアルタイムに反映させることで、開発のテンポアップを図っている。

HOT Deploy機能はYmirの自動生成機構のようなリクエストドリブンの自動生成機構とは非常に相性が良いのだが、その反面以下のような問題がある。

  • リクエストの度にClassLoaderを差し替えているため、リクエストスコープよりライフサイクルの長いスコープを扱う際に注意が必要。具体的には、例えばHttpSessionにHOT Deploy対象クラスのオブジェクトをバインドした場合、普通にオブジェクトを取り出すとClassCastExceptionがスローされてしまう。
  • HOT Deploy対象でないクラスの中でHOT Deploy対象のクラスを使う場合に注意が必要。標準のS2のHOT Deployでは、HOT Deploy対象でないクラスの中でHOT Deploy対象のクラスを使うと、HOT Deploy対象のクラスも通常のクラスローダから読み込まれてしまうため、HOT Deployしてくれると思ったらしてくれないという事態が発生する。Ymir(正確にはYmirがベースとしているs2-pluggableモジュール)ではこの事態を避けるため、HOT Deploy対象のクラスは常にHotdeployClassLoaderからロードするようにしているが、これだとHOT Deploy対象でないクラスのメソッドの引数にHOT Deploy対象のクラスのオブジェクトを渡すとClassCastExceptionがスローされてしまう事態が発生する。

S2のHOT Deploy対応フレームワークを用いたアプリケーションの開発ではHOT Deploy関連のトラブルが多く、かつ開発者がHOT Deployの仕組みを良く知らない場合は原因の特定に非常に時間がかかる。また「HOT DeployモードとCool Deployモードで挙動が違う」などのトラブルも多い。YmirではS2のHOT Deploy機構を独自に改変して上記トラブルがほぼ発生しないようにしているが、それでもHOT Deployがらみのトラブルに見舞われることはゼロではない。

ところでS2以外のHOT Deploy系ソリューションとして、有償ではあるがJavaRebelという製品がある。こちらはS2のHOT Deployとは異なる方法でクラスの動的変更を実現しており、上記のような問題が発生しないようになっている。ただしこちらはこちらで以下の制約がある。

最新版のYmir(0.9.6-SNAPSHOT)ではS2のHOT Deployの代わりにJavaRebelを使うことができるようになっている。JavaRebelを使うには、以下のようにすればよい。

  • S2のHOT Deploy機構を無効化するために、app.propertiesに以下のエントリを追加する。
s2container.classLoading.disableHotdeploy=true
  • app.diconに以下のエントリを追加する。
  <component class="org.seasar.ymir.interceptor.impl.AlternativeHotdeployInterceptor" />
  • JavaRebelが有効になるように、サーブレットコンテナの起動時のJVMオプションに例えば以下のようなエントリを追加する。
-noverify
-javaagent:C:\javarebel\javarebel.jar
-Drebel.dirs=C:\eclipse\workspace\app\src\main\webapp\WEB-INF\classes

これで開発モードではJavaRebelが有効になる。リリースモードではJavaRebelは無効になる。

JavaRebelを利用することでHOT Deploy関連のトラブルをほとんど気にせず開発ができるようになるかもしれない。予算が潤沢にあるプロジェクトではJavaRebelの利用を検討してみてはいかがだろうか。