[Seasar-user:19289] Re: ライブラリの格納先について

Koichi Kobayashi [E-MAIL ADDRESS DELETED]
2010年 2月 11日 (木) 15:00:01 JST


小林 (koichik) です.

Date:    Wed, 10 Feb 2010 12:00:58 +0000
From:    "奥野 守" <[E-MAIL ADDRESS DELETED]>
To:      [E-MAIL ADDRESS DELETED]
Subject: [Seasar-user:19277] Re: ライブラリの格納先について

> パターン2:
> ・[ライブラリ]をWEB-INF/libにのみ格納する。
>   (jboss配下には格納しない)
> 
> 結果2:
> ・hotdeploy(再配備)時、クラスのアンロードが行われるものの、
>   数回再配備を繰り返すとOutOfMemoryError(PermGen space)
>   # アンロードできているクラス/できていないクラスの詳細は
>     まだ確認できていない状態です。

Dolteng で作成した SAStruts + S2JDBC のアプリと
Tomcat 6.0.24 の組み合わせを以下の手順で確認しました.


1.Tomcat の JVM 起動オプションに -verbose:class を指定し,
VisualJVM を起動しておく.

2.Tomcat を起動して SAStruts + S2JDBC アプリの
画面を開く.

3.VisualJVM で Heap Dump を取得し,Tomcat の 
WebappClassLoader のインスタンスに該当 Web アプリを
ロードした WebappClassLoader が含まれていることを確認.
(jarNames フィールドの内容から判断できます)

4.管理画面から SAStrtus + S2JDBC アプリをアンデプロイする.

5.すぐにはアンロードされないので,VisualJVM から
GC を何度か発生させる.

6.VisualJVM の Heap Dump を取得し,Tomcat の 
WebappClassLoader のインスタンスに該当 Web アプリを
ロードした WebappClassLoader が含まれていない (GC された)
ことを確認.

7.-verbose:class のログから,ロードされたクラスと
アンロードされたクラスのマッチングを行い,該当アプリに
含まれるクラスが残ってないことを確認.


以上の結果から,SAStruts + S2JDBC の最低限の
アプリケーションは Tomcat から問題なくアンデプロイ
できています.

そちらのアプリ + JBoss でも同じように確認してみてください.

ロードされたクラスとアンロードされたクラスのマッチングは
次のようなクラスを作って行ったので参考にどうぞ.
# こういう時に LL 使わないと格好悪い気がするけどいいのだ.

ログを保存して実行すると,ロードされたのにアンロード
されていないクラスがコンソールに出力されます.
ファイルのパスとエンコーディングは実際に合わせてください.

public class ClassLeakTest extends TestCase {
    Pattern loadPattern = Pattern.compile("\\[Loaded (\\S+) from (.*)]");
    Pattern unloadPattern = Pattern.compile("\\[Unloading class (\\S+)]");

    public void test() throws Exception {
        BufferedReader r = new BufferedReader(new InputStreamReader(
            new FileInputStream("log.txt"),
            "Shift_JIS"));
        Map<String, String> map = new HashMap<String, String>();
        String line = null;
        while ((line = r.readLine()) != null) {
            Matcher matcher = loadPattern.matcher(line);
            if (matcher.matches()) {
                String className = matcher.group(1);
                String from = matcher.group(2);
                map.put(className, from);
                continue;
            }
            matcher = unloadPattern.matcher(line);
            if (matcher.matches()) {
                String className = matcher.group(1);
                map.remove(className);
            }
        }
        for (String className: map.keySet()) {
            System.out.println(className + " from " + map.get(className));
        }
    }
}


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