10

Glassfishインスタンスは、しばらくの間2週間ごとにダウンしましたjava.lang.OutOfMemoryError: PermGen space。PermGenスペースを512MBに増やし、メモリ使用量のダンプを開始しましjstat -gcた。2週間後、PermGenスペースが着実に増加していることを示す次のグラフを思いつきました(x軸の単位は分、y軸はKBです)。 PermGenの使用量の増加のグラフ

私はエラーを特定できるある種のプロファイリングツールを探し回ってみました。ここでSOが言及したjmapのスレッドは、非常に役立つことがわかりました。からダンプされた約14000行のうちjmap -permstats $PID、約12500行が含まれgroovy/lang/GroovyClassLoader$InnerLoaderており、独自のGroovyコードまたはGroovy自体からのある種のメモリリークを示しています。Groovyは関連するコードベースの1%未満を構成していることを指摘する必要があります。

以下の出力例:

class_loader    classes bytes   parent_loader   alive?  type

<bootstrap> 3811    14830264      null      live    <internal>
0x00007f3aa7e19d20  20  164168  0x00007f3a9607f010  dead    groovy/lang/GroovyClassLoader$InnerLoader@0x00007f3a7afb4120
0x00007f3aa7c850d0  20  164168  0x00007f3a9607f010  dead    groovy/lang/GroovyClassLoader$InnerLoader@0x00007f3a7afb4120
0x00007f3aa5d15128  21  181072  0x00007f3a9607f010  dead    groovy/lang/GroovyClassLoader$InnerLoader@0x00007f3a7afb4120
0x00007f3aad0b40e8  36  189816  0x00007f3a9d31fbf8  dead    org/apache/jasper/servlet/JasperLoader@0x00007f3a7d0caf00
....

では、どのコードがこれを引き起こしているのかをもっと知るにはどうすればよいですか?

この記事から、Groovyコードがどこかに動的にクラスを作成していると推測します。そして、jmapからのダンプから、死んだオブジェクト/クラス(?)のほとんどが同じparent_loaderを持っていることがわかりますが、このコンテキストでそれが何を意味するのかはわかりません。ここから先に進む方法がわかりません。

補遺

後発者の場合、受け入れられた回答は問題を解決しないことを指摘する価値があります。クラス情報をあまり保存しないことで、再起動するまでに必要な期間を10倍に延長するだけです。私たちの問題を実際に修正したのは、それを生成したコードを取り除くことでした。メソッドとクラスのアノテーションとしてGroovyを使用してカスタム制約をスクリプト化できる、検証(契約による設計)フレームワークOValを使用しました。プレーンJavaで明示的な事前条件と事後条件を優先してアノテーションを削除するのは退屈でしたが、それで作業は完了しました。OVal制約がチェックされるたびに、新しい匿名クラスが作成されていて、何らかの形で関連するクラスデータがメモリリークを引き起こしていたのではないかと思います。

4

2 に答える 2

3

同様の問題が発生しました(クラッシュの間隔は1週間)。問題は、Groovyがメタメソッドをキャッシュすることのようです。このディスカッションバグレポートに基づいて、このコードを使用することになりました。

GroovyClassLoader loader = new GroovyClassLoader();
Reader reader = new BufferedReader(clob.getCharacterStream());
GroovyCodeSource source = new GroovyCodeSource(reader, name, "xb3.Classifier");
Class<?> groovyClass = loader.parseClass(source);
Object possibleClass = groovyClass.newInstance();
if (expectedType.isAssignableFrom(possibleClass.getClass())) {
    classifiers.put((T) possibleClass, name);
}
reader.close();
// Tell Groovy we don't need any meta
// information about these classes
GroovySystem.getMetaClassRegistry().removeMetaClass(possibleClass.getClass());
// Tell the loader to clear out it's cache,
// this ensures the classes will be GC'd
loader.clearCache();
于 2012-05-07T14:40:59.030 に答える
-6

Sun JVMを使用している場合は、IBMJVM用に変更してください。正常に動作することを願っています:)

于 2011-05-18T14:16:34.180 に答える