[Seasar-user:13152] Re: [HotDeploy] AnnotationのAnnotation

Kazuya Sugimoto [E-MAIL ADDRESS DELETED]
2008年 3月 5日 (水) 11:34:54 JST


杉本です。

小林さん、詳細な説明ありがとうございます。
とても分かりやすかったです。
永久保存版にしておきます。

ご指摘のようにHotdeploy対象外のクラスで扱っている部分がありました。

アノテーションはHotDeploy対象外にするように以下の設定を追加すると、
期待通りに動作するようになりました。
<initMethod name="addIgnorePackageName">
  <arg>"HogeAnnoのパッケージ"</arg>
</initMethod>

ありがとうございました。


08/03/04 に Koichi Kobayashi さんは書きました:
> 小林 (koichik) です.
>
> クラスローダのディープな世界へようこそ.
>
> まず,Java ではクラスは VM 上に一つではなく,
> 同じクラスでもクラスローダごとに複数存在する
> 場合があります.
> そして異なったクラスローダでロードされたクラスは,
> たとえ同じ .class ファイルからロードされたもので
> あっても異なったクラスとして扱われます.
>
> 例えば Foo というクラスがクラスローダ A と B に
> ロードされた場合,Foo(A) と Foo(B) は異なった
> クラスであり,そのインスタンスも別物です.
> Foo(A) 型の変数に Foo(B) のインスタンスを代入
> することもできません.
>
> HOT deploy は,リクエストごとに異なるクラスローダを
> 使ってクラスをロードします.
> しかし,一部のクラスはオリジナルのクラスローダに
> ロードされます.
>
> その場合に代入できない問題に対処するため,
> オリジナルのクラスローダにロード済みのクラスは
> HOT deploy 用のクラスローダにはロードしないように
> しています.
>
> が,しかし.
> それだけでは回避できない状況もあります.
>
> Date:    Tue, 4 Mar 2008 09:42:06 +0900
> From:    "Kazuya Sugimoto" <[E-MAIL ADDRESS DELETED]>
> To:      [E-MAIL ADDRESS DELETED]
> Subject: [Seasar-user:13144] [HotDeploy] AnnotationのAnnotation
>
> > // HogeAnnoが付いているアノテーションでもnullになってしまいます
> >    Annotation annoAnno =
> > annotation.annotationType().getAnnotation(HogeAnno.class);
> > }
> >
> > また、isAnnotationPresentでもtrueが返ってくるはずがfalseになりました。
> > if(annotation.annotationType().isAnnotationPresent(HogeAnno.class)) {
> > ・・
> > }
>
> HogeAnno.class というリテラルを使っていますが,
> この場合の Class オブジェクト (Class クラスの
> インスタンス) は,このコードを含むクラスと
> 同じクラスローダに読み込まれた HogeAnno クラスを
> 表現します.
>
> おそらく,このコードを含むクラスは
> HotdeployClassLoader ではなく,本来のクラスローダ
> (以下 Tomcat に合わせて WebappClassLoader) に
> ロードされています.
> そのため,HogeAnno.class もまた WebAppClassLoader に
> ロードされいるクラスを表しています.
>
> しかし.
> HobeAnno が WebAppClassLoader にロードされる
> タイミングは必要になるまで遅延される場合があります.
> おそらく,最初にこのコードを実行されるまでは,
> WebappClassLoader には HogeAnno はロードされません.
> それよりも前に,HogeAnno が付けられたオブジェクトが
> このコードに渡されます.ここに注意.
>
> つまり,アノテーションの付けられているクラス
> がロードされる時点では,HogeAnno は
> WebappClassLoader にはロードされておらず,
> HotdeployClassLoader にロードされていると
> 考えられるわけです.
>
> そして上記コードが実行される際に HogeAnno が
> WebappClassLoader にロードされますが,
> getAnnotation() で取得できる HogeAnno は
> HotdeployClassLoader にロードされたものであり,
> 上記コードが使用する WebappClassLoader に
> ロードされた HogeAnno とは異なったクラスとして
> 扱われてしまいます.
>
> そんなわけで (どんなわけで?),
> getAnnotation(HogeAnno.class) は null を返し,
> isAnnotationPresent(HogeAnno.class) は false を
> 返すことになります.
> ぜぇぜぇ.
>
> > getAnnotationsで配列で取得してみると以下の3つが確認できました。
> > java.lang.annotation.Target
> > java.lang.annotation.Retention
> > HogeAnno(クラス名を見ただけで代入や比較では確認してません)
>
> ここで取得した HogeAnno のインスタンスに対して
> getClass().getClassLoader() をすると
> HotdeployClassLoader が返ってくるはずです.
> # 初回のみ.
>
> 一方,HogeAnno.class.getClassLoader() では
> WebappClassLoader が返ってくるはずです.
>
> HOT deploy でも,最初のリクエストを処理している
> 途中で HogeAnno が WebappClassLoader にロード
> されるため,2 回目以降のリクエストでは
> HotdeployClassLoader にロードされることはなく,
> うまく動くことになります.
>
>
> 対策ですが,HogeAnno が常に HotdeployClassLoader で
> 扱われるようにするか,常に WebappClassLoader で
> 扱われるようにするかのどちらかになります.
>
> 常に HotdeployClassLoader で扱われるようにするには,
> 上記コードも Hotdeploy 対象のクラスで行うように
> する必要があります.<root>.util.XxxUtil クラスなどで
> あれば HOT deploy 対象となります.
>
> 常に WebAppClassLoader で扱われるようにするには,
> HogeAnno をルートパッケージ以外に移動するか,
> convention.dicon で NamingConvention に
>
> <initMethod name="addIgnorePackageName">
>  <arg>"HogeAnnoのパッケージ"</arg>
> </initMethod>
>
> とする必要があります.
>
>
> --
> <component name="koichik">
>    <property name="fullName">"Koichi Kobayashi"</property>
>    <property name="email">"[E-MAIL ADDRESS DELETED]"</property>
>    <property name="blog">"http://d.hatena.ne.jp/koichik"</property>
> </component>
>
> _______________________________________________
> Seasar-user mailing list
> [E-MAIL ADDRESS DELETED]
> https://ml.seasar.org/mailman/listinfo/seasar-user
>


-- 
Kazuya Sugimoto
Microsoft MVP Visual Developer - Solutions Architect
http://d.hatena.ne.jp/sugimotokazuya/


Seasar-user メーリングリストの案内