[Seasar-user:5230] Re: JUnitでOutOfMemory

Koichi Kobayashi [E-MAIL ADDRESS DELETED]
2006年 11月 21日 (火) 16:00:08 JST


小林 (koichik) です.

Date:    Tue, 21 Nov 2006 13:03:55 +0900
From:    Tetsuya Toba <[E-MAIL ADDRESS DELETED]>
To:       [E-MAIL ADDRESS DELETED]
Subject: [Seasar-user:5229] JUnitでOutOfMemory

> 現在、JUnitを使ってテストを行っているのですが、プロジェクト内の
> テストケースを全て実施すると、OutOfMemoryError となってしまいます。

おそらく JUnit の TestCase を直接継承した
テストクラスをお使いだと思われますが,
Seasar2 の提供する S2TestCase を継承した
テストクラスを作成すると OutOfMemoryError で
悩まされる可能性はかなり減ると思います.

もし S2TestCase を継承したテストクラスで
OutOfMemoryError が起きているならかなり
深刻かもしれません.

> 簡単なプログラムを作って追試してみましたが、SingletonS2Container
> またはS2Containerでコンポーネントの生成を繰り返すだけで、発生して
> しまいます。

JUnit の TestCase を直接継承した場合も同様ですが,
このようなコードを書くと簡単に OutOfMemoryError に
なります.

S2AOP では,アスペクトを適用する際に対象クラスの
サブクラスを動的に生成し,コンテキストクラス
ローダーにロードします.
添付していただいたサンプルや JUnit の TestCase を
直接継承したテストケースでは,コンテキストクラス
ローダーはシステムクラスローダーです.

クラスローダーに一度ロードされたクラスは,
クラスローダーが GC されない限りアンロード
されません.

そのため,S2Container の生成が行われるたびに
新たなクラスがシステムクラスローダーにロード
されますが,システムクラスローダーは決して
GC されないのでパーマネント領域が枯渇し,最後は
OutOfMemoryError となります.

S2TestCase ではこのような事態を避けるため,テスト
メソッドごとに一時的なクラスローダーを作成して
コンテキストクラスローダーに設定します.
通常,一時的なクラスローダーはテストメソッドが
終了すると GC されるので,S2AOP が動的に作成した
クラスもアンロードされます.

> どうすればこの問題を回避できるでしょうか?

もし JUnit の TestCase を直接継承しているなら,
S2TestCase を継承できないか検討してください.
もし S2TestCase が使えないなら,S2TestCase の
スーパークラスである

org.seasar.framework.uni.S2FrameworkTestCase

の setUpContainer() および tearDownContaier()
メソッドを参考に,setUp() および tearDown() で
一時的なクラスローダーをコンテキストクラス
ローダーに設定してください.


一時しのぎであれば,JVM のオプションで

-XX:MaxPermSize=128m

のようにパーマネント領域を大きめにすることで
回避できるかもしれません.


--
<signature>
   <name>Koichi Kobayashi</name>
   <e-mail>[E-MAIL ADDRESS DELETED]</e-mail>
</signature>




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