[mayaa-user:938] Tomcat7 + Mayaa1.1.28 + HotSpot VMにてload関数でPermGenを無駄に消費してしまうようです

Susumu ISHIGAMI [E-MAIL ADDRESS DELETED]
2012年 10月 8日 (月) 16:32:21 JST


Mayaa開発者様
おせわになっております。石上です。

Tomcat7 + Mayaa1.1.28 + HotSpot VMにおいて
load関数やexecプロセッサーで外部jsファイルを開くと、
リクエストを受け付けるごとにPermGen領域を使用してしまう現象を確認しましたので報告致します。

具体的には、
defaule.mayaaに
	<m:beforeRender><![CDATA[
		load("/util.mjs");
	]]></m:beforeRender>

と記述したとすると、
org.seasar.mayaa.impl.cycle.script.rhino.SourceCompiledScriptImpl.compileFromSource(Context,
SourceDescriptor)
にて、
source.getTimestamp()
で、ファイルのタイムスタンプを調べています。

org.seasar.mayaa.impl.source.ApplicationSourceDescriptor.getTimestamp()の実装を読むと、
    public Date getTimestamp() {
        if (canUseFile()) {
            return _fileSourceDescriptor.getTimestamp();
        }
        return new Date(IOUtil.getLastModified(_url));
    }
のようになっています。

ここで、canUseFile()はfalseを返します。
これは内部の
    if (_fileSourceDescriptor.exists() == false) {
とい行で、

     public boolean exists() {
        prepareFile();
        return (_file != null) && _file.exists();
    }
の中、

file.exists()
はfalseを返します。

fileが"/util.mjs"のようにルート始まりになっているためです。

getTimestamp内で、canUseFile()がfalseを返してしまうので、
return _fileSourceDescriptor.getTimestamp();
ではなく、
return new Date(IOUtil.getLastModified(_url));
が実行されます。

IOUtil.getLastModifiedは
    public static long getLastModified(URL url) {
        File file = getFile(url);
        if (file != null) {
            return file.lastModified();
        }
        return System.currentTimeMillis();
    }
という実装になっていますので、
_urlのプロトコルが"file:///""でなければ、タイムスタンプを取得できず、常に現在時刻を返す仕様のようです。

ここで、
Eclipse J2EE Preview (Jettyベース)では、
_urlがfile://で始まっているのですが、
Tomcat7で試したところ、
jndi://になっていました。

ここから先はRhino内部へ行ってしまうため詳細に追えていませんが、スクリプトをコンパイルすると、
クラスが一つロードされるのではないかと思います。

HotSpot VMでは、クラスロードはPermGen領域に行われ、この領域は、いわゆるYoung GCでは
クリアされないため、いずれPermGen使用率が100%となり、Full GCが発生してしまうと思います。

Tomcat6でも同様の現象を確認したため、おそらく同じようになっているのだと思います。
Tomcat5以前は試していないのでわかりません。

うまく整理できず、込み入った報告となってしまいましい申し訳ありません。
当初自分が複雑なことをやっているためかと思ったのですが、
サンプルベースのシンプルなプロジェクトでも上記現象を再現しましたので、やはり報告せねばと思いました。
小さいプロジェクトですが、zipにかためて4KB程の容量になってしまうため、MLに送信することがためらわれます。
送付先をご指定頂ければ、送付させて頂くことができます。

自分は、この問題のために、プロジェクト全体でload関数を使うことをやめ、mayaaファイルにスクリプトファイルを
ベタ書きすることで対処していますが、load関数はマニュアルにも記載されている一般的な方法であると思いますので、
ご確認頂けると良いかと思います。

万が一自分の勘違いによる的はずれな報告であったら、申し訳ありません。

以上、何卒よろしくお願い致します。


-- 
/**
* @twitter  http://twitter,com/susumuis
* @blog     http://d.hatena.ne.jp/s-ishigami/
* @github  http://github.com/susumuishigami
* @gmail   susumu.ishigami @ gmail.com
*/
Susumu ISHIGAMI


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