[Seasar-user:5892] Re: [S2Container]S2FrameworkTestCase/UnitClassLoaderの実装について
Koichi Kobayashi
[E-MAIL ADDRESS DELETED]
2007年 1月 25日 (木) 18:00:38 JST
小林 (koichik) です.
Date: Thu, 25 Jan 2007 13:29:36 +0900
From: kubo <[E-MAIL ADDRESS DELETED]>
To: <[E-MAIL ADDRESS DELETED]>
Subject: [Seasar-user:5886] [S2Container]S2FrameworkTestCase/UnitClassLoaderの実装について
> <現象>
>
> S2TestCaseを継承したテストをEclipseのJUnitで一括実行すると
> Memoryの使用量がMethod毎に(ほぼ定量的に)増えていって、
> 最終的にOutOfMemoryになる。OutOfMemoryのMessageは、“PermGen space”。
>
> TestMethodはおよそ200。それぞれincludeするdiconを必要なものだけに
> 絞っているが、少し長続きするだけで最終的にはOutOfMemoryとなる。
現象から一番考えられるのは,システムクラスローダーに
ロードされたクラスから,UnitClassLoader にロードされた
クラス(S2によってエンハンスされたクラス)への参照が
あるのではないかということです.
キャッシュなど.
そうなると UnitClassLoader がアンロードできず,
パーマネント領域が枯渇することになります.
> その場合、ClassLoadingする際に、parentのClassLoaderが該当Classを
> 読み込んでしまわないでしょうか?
> つまり、SystemClassLoaderがClassを読み込んでいないのでしょうか?
例えば Dao など,S2AOP でエンハンスされたコンポーネントを
取得して
System.out.println(dao.getClass().getClassLoader());
すれば,どのクラスローダーからロードされているか
確認できます.
> それとも、そのようなことはなく(少なくともOutOfMemoryの原因とは無関係)、
> UnitClassLoaderの実装は現状ので正しいのでしょうか?
少なくとも,エンハンスされたクラスは UnitClassLoader に
ロードされます.
> もしUnitClassLoaderは問題ないのであれば、その理由(仕組み)を
> 教えていただきたいのですがよろしいでしょうか?
S2AOP は,エンハンスしたクラスのバイトコード(byte[])を
コンテキストクラスローダーの ClassLoader#defineClass() で
ロードします.このメソッドは protected なのでリフレクション
経由で呼び出します.
org.seasar.framework.aop.javassist.AbstractGenerator の
toClass(ClassLoader, CtClass) メソッドがそれです.
そして,ClassLoader#defineClass() の実装は loadClass() と
異なり,親クラスローダーへ委譲しません.
そのクラスローダー自身にロードされます.
結果的に,UnitClassLoader#loadClass() を経由する
通常のクラスは親クラスローダー(システムクラスローダー)に
ロードされ,S2AOP によってエンハンスされたクラスのみが
UnitClassLoader にロードされます.
やり方は違いますが,同じようなことを
org.seasar.framework.container.util.MemoryLeakTest で
行っているので参考にしてください.
--
<signature>
<name>Koichi Kobayashi</name>
<e-mail>[E-MAIL ADDRESS DELETED]</e-mail>
</signature>
Seasar-user メーリングリストの案内