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が発生してしまう。

が、それでも回避できないのが、

のよう。

このあたりは、
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自体発生しないで正常終了する。
クラスロードのタイミングはよくわからん。。。