Hot Deploy
Hot DeployとはJavaのソースコードを修正した際にアプリケーションサーバの再起動無しに、
結果をすぐ確認できるもの。
じゃあこれをどう実現しているかというと、
クラスローダに読み込まれたクラスファイルは変更できない。
なのでHTTPリクエストのたびにクラスローダをつくって、変更後のクラスファイルを読み込む。
HotdeployFilterをみると下記のようにリクエストのたびにHotdeployBehaviorのstart、stopをよんでいる。
このstartからstopまでがHot Deployの範囲。
HotdeployUtilのstart、stopでも同様。
HotdeployBehavior ondemand = (HotdeployBehavior) provider; ondemand.start(); try { request.setAttribute(KEY, Thread.currentThread() .getContextClassLoader()); chain.doFilter(request, response); } finally { request.removeAttribute(KEY); ondemand.stop(); }
HotdeployBehaviorのstartは下記のとおり。リクエストのたびにHotdeployClassLoaderを作っている。
originalClassLoader = Thread.currentThread().getContextClassLoader();
hotdeployClassLoader = new HotdeployClassLoader(originalClassLoader,
namingConvention);
Thread.currentThread().setContextClassLoader(hotdeployClassLoader);
S2ContainerImpl container = (S2ContainerImpl) SingletonS2ContainerFactory
.getContainer();
container.setClassLoader(hotdeployClassLoader);
HotdeployClassLoaderのloadClassはでは下記のように親クラスで読み込まれたものはHot Deployの対象にしないようにしている。
Class clazz = findLoadedClass(className); if (clazz != null) { return clazz; } clazz = ClassLoaderUtil.findLoadedClass(getParent(), className); if (clazz != null) { return clazz; } clazz = defineClass(className, resolve); if (clazz != null) { return clazz; }
このようにしたのは、
http://svn.seasar.org/browse?view=rev&root=s2container&revision=1236
からのよう。
こうしないと、システムクラスローダやWebappクラスローダで読み込まれたクラスでClassCastExceptionが発生してしまう。
が、それでも回避できないのが、
- [Seasar-user:5889] [Teeda]ThrowsInterceptorでthrowした例外が初回はcatchできない(hotdeploy)
- [Seasar-user:13144] [HotDeploy] AnnotationのAnnotation
のよう。
このあたりは、
http://d.hatena.ne.jp/koichik/20061118#1163869222
にも書かれている。
このエントリはすごくいいと思うんですが、
これらの中で,HOT deploy できないものが一つだけあります.
それは
* MessageService
です.
http://d.hatena.ne.jp/koichik/20061118#1163869222
はPrintServiceの気がするんですが。。。
ともあれ (JW),ためしにこのエントリのTestクラスのClass.forNameを消して
for (int i = 0; i < 3; ++i) { HotdeployUtil.start(); try { PrintService printer = (PrintService) container .getComponent("printService"); printer.print(); } catch (ClassCastException e) { e.printStackTrace(); } HotdeployUtil.stop(); }
とすると、なぜかうまくいく。^^);
ClassCastExceptionをcatchするかと思いきやClassCastException自体発生しないで正常終了する。
クラスロードのタイミングはよくわからん。。。