S2Container と Tomcat のリロード
http://d.hatena.ne.jp/t-katochin/20060623/1151082516
の最後で指摘されてるように,Tomcat 上で S2AOP を使うとリロードされても S2Container が GC されず,メモリ不足で例外が発生する場合があります.
この現象は以前から聞いてはいましたが,きっちり調べることはしていませんでした.
理由は
- 運用環境でリロードなんてあり得ない.
- 開発/テスト環境では Tomcat を再起動すればいい
ということで,致命傷になるとは考えていなかったためです.
が,しかし.
某巨大掲示板でも困ってるという人がいるので調べてみました.
まず,かとちんご指摘の循環参照について.
S2AOP を使うとアスペクトが適用されるメソッド毎に 〜$$MethodInvocation$$
みたいな名前のクラスが作成されます.
こいつは
public static class MethodInvocationTemplate implements S2MethodInvocation { private static Class targetClass; private static Method method; private static MethodInterceptor[] interceptors; private static Map parameters; ・・・
というように static
フィールドを持っています.
このうち,parameters
というフィールドに設定される Map
にはアスペクトが適用されるコンポーネント定義 (ComponentDef
) への参照が含まれます.
そして ComponentDef
はアスペクトが適用された (エンハンスされた) クラスへの参照を持ち,アスペクトが適用されたクラスは上の 〜$$MethodInvocation$$
への参照を持つので,めでたく循環参照となります.
その是非はともかく,この循環参照そのものは S2Container
が GC されない直接の原因ではありません.
Tomcat 上で普通に S2 を使う場合,S2 もアプリのクラスも WEB-INF/lib
以下に配置され,それらは Web アプリ毎に用意されるクラスローダー,WebappClassLoader
によってロードされます.
S2AOP によってエンハンスされるクラスも同じ WebappClassLoader
にロードされます.
上で循環参照しているクラスとそのインスタンスが全て単一の WebappClassLoader
によってロードされるため,その外からの参照が無くなればクラスローダーもろとも GC されます.
よって,この循環参照自体は GC を阻害するものではありません.
が,しかし.
実際には S2AOP を使うと S2Container
は GC されません.
S2AOP を使わなければ GC されます.
この原因がよく分からなかったのですが,実は S2AOP を使っても使わなくても,WebappClassLoader
が GC されずに残っていたのですね.
WebappClassLoader
が到達可能だと,それによってロードされたクラスも GC されず,その static
フィールドから到達可能なオブジェクトも GC されません.
つ・ま・り
〜$$MethodInvocation$$
の parameters
フィールドから到達可能であるため,S2AOP を使うと S2Container
が GC されなくなってしまうわけです.
実際には Tomcat じゃなく,JUnit なんかで試しても S2Container
をロードしたクラスローダーが GC されていないことが分かりました.
し・か・も
GC されないのは最初に S2Container
などをロードするのに使われるクラスローダーだけで,リロードされた後のクラスローダーなどは GC されちゃったり.
結局,その原因は commons-logging (の使い方) だったようです.
たぶん有名な話なのだと思いますが,LogFactory#release()
とか使って Log
なんかを解放してあげないといけないのね.
http://wiki.apache.org/jakarta-commons/Logging/UndeployMemoryLeak?action=print
http://jakarta.apache.org/commons/logging/guide.html#Classloader_and_Memory_Management
とはいえ,commons-logging も WEB-INF/lib
にあって同じクラスローダーからロードされているわけで...
ちょっと腑に落ちないところはありますが,LogFactory#release()
を呼んであげることで S2Container
もそれをロードしたクラスローダーも GC されるようになりました.
trunk (S2.4 系) は既に修正&コミット済みです.
ついでに,S2Container#destroy()
の際に ComponentDef
や子の S2Container
への参照をクリアするようにしました.
S2.3 系も近日中にコミットする予定.
そんなわけで (どんなわけで?),結論としては commons-logging の作法を守っていなかった S2 本体がメモリリークしていたということになります.心より恥じる.
Tomcat のリロードで悩んでいた方にはお詫び申し上げます.
それから,この問題に気づくきっかけを頂いたかとちんに感謝します.
Mensware in Milan Spring/Summer 2007
夏はまだこれからなのに秋冬の新作が入荷し始めた今日この頃ですが,ミラノでは早くも春夏コレクションがスタート!!
初日は JIL SANDER,Dolce & Gabbana,Burberry Prorsum,Prada など.
JIL SANDER
http://www.vogue.co.uk/shows/photos/Default.aspx?ShowID=3586
秋冬同様,ボックス型のシルエットの細身のパンツ.
ようするに Raf らしいコレクションってことね.
おいらは Milan 時代がよかったよ...
Raf の JIL はおいらには魅力がないっす.
Burberry Prorsum
http://www.vogue.co.uk/shows/photos/Default.aspx?ShowID=3593
Christopher Bailey はシーズン毎にイメージがガラリと変わることが多いわけですが,ちょっとクラシックというか London 色が強かった最近と比べると軽やかになった感じ.
でもでも,そんなに好みという感じでもなさそう.
グレーが多いね.
Roberto Cavalli
http://www.vogue.co.uk/shows/photos/Default.aspx?ShowID=3713
Tom Ford,Milan Vukmirovic が去った今,オイラ好みの色っぽさを一番期待できそうなのがここかなとか思ったり.
でも,これだ! ってのは見当たらず.
春夏最大の注目はやはり GUCCI.
John Ray が去って Frida Giannini による最初のメンズコレクション.
レディースみたいにプリントであふれてたらどうしよう...
この秋冬のレディースの雰囲気だったら悪くないかもしれないけど,春夏 (06SS) の雰囲気だったらイヤだなぁ.
ともあれ (JW),GUCCI は明後日.楽しみ♪