2

プロジェクトで互いに連携する 2 つの別個の Web アプリでいくつかの問題を実験しています。X 回のデプロイの後、悪名高い「java.lang.OutOfMemoryError: PermGen space」エラーが発生します。

そのため、私はしばらくの間、VisualVM を使用して PermGen スペースを監視し、アプリを継続的に再デプロイして、何が起こっているかを確認してきました。

そして、ここで奇妙な動作:

最初に、最初のアプリを 15 回以上再デプロイしました。動作は予想どおりでした。メモリ ダイアグラムは、最大サイズ (67MB) に近づくまで、絶えず増加するはしごのようでした。この時点でメモリは解放され、初期レベルに戻ります。

2番目のアプリケーションを再デプロイしたときも同じです。

次に、両方を同時に再展開しようとしました (Tomcat はこれを順番に実行します)。はしごの「ステップ」のサイズは大きくなりましたが、動作は単一の展開と同じでした。

それから私は最後のテストをしました。メモリが限界に近づくまで両方のアプリを同時に再展開し、その後、アプリの 1 つだけを再展開しました。そして..出来上がり: PermGen ERROR.

それで..ここで一体何が起こっているのですか?

VisualVMの図。前半 (左) は、単一の展開 (アプリケーション 1 および 2) に対応します。後半(右)は、限界を超えてエラーになった時点を表しています。

ここに画像の説明を入力

ありがとうございました!

4

1 に答える 1

1

OPはこちら。

私はこれについていくつかの調査を行ってきましたが、私の結論は、permgen スペースに関連する JVM の動作を完全に理解することは多かれ少なかれ不可能であるということです:)

この時点で、クラスローダに関連するメモリ リークの可能性に関するいくつかのトピックを読みました。クラスの定義は未使用のままですが、permgen-limit を超えるまでメモリに保存されます。それが理論です。しかし、このリークの原因について何かを本当に知ることは非常に困難です。つまり、不適切なプログラミングが原因でアプリケーションでメモリ リークが発生しているかどうかを知ることは非常に困難です。

最後に、この問題に対する私の解決策は、メモリサイズを増やし、いくつかのフラグを使用することです。これは、スタックオーバーフローの関連トピックで読んだことがあります。これは、ユーザーが permgen エラーを見つけたときに使用するものです。これが解決策なのか、単にこの痛みを忘れる方法なのかはわかりません... ;)

Catalina.sh (TOMCAT) に、次の行を追加しました。

export CATALINA_OPTS="-Xms64m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m -XX:+UseConcMarkSweepGC -XX:+CMSClassUnloadingEnabled"

どこ:

-Xms64mは、Java ヒープ メモリの最小サイズを 64MB に設定します。

-Xmx512mは、Java ヒープ メモリの最大サイズを 512MB に設定します。

-XX:PermSize=128mは、permgen メモリの初期サイズを 128MB に設定します。

-XX:MaxPermSize=512mは、permgen メモリの最大サイズを 512MB に設定します。

-XX:+UseConcMarkSweepGC : jvmは、JavaヒープのTenured世代にConcurrent Mark Sweep Garbage Collectorを使用します

-XX:+CMSClassUnloadingEnabled : ガベージ コレクターは PermGen を一掃し、使用されなくなったクラスを削除します。

于 2013-08-26T08:26:07.117 に答える