[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 メーリングリストの案内