41

私は標準の Lift プラットフォーム (maven と jetty) で開発しています。私は繰り返し(数日に1回)これを取得しています:

Exception in thread "7048009@qtp-3179125-12" java.lang.OutOfMemoryError: PermGen space
2009-09-15 19:41:38.629::WARN:  handle failed
java.lang.OutOfMemoryError: PermGen space

これは私の開発環境にあります。サーバーを再起動し続けることができるので問題ありません。展開では、これらの問題は発生していないため、実際の問題ではありません。私はただ興味があります。

私はJVMについてあまり知りません。永続的な世代のメモリは、クラスやインターンされた文字列などのためのものであると考えるのは正しいと思いますか? 私が覚えているのは、.NET メモリ モデルと少し混同されていることです...

これが起こっている理由は何ですか?デフォルトは非常に低いですか?Scala が Function オブジェクトや同様の FP 用に作成しなければならないすべての補助オブジェクトと関係がありますか? 新しく記述したコードで Jetty を再起動するたびに (数分ごとに)、クラスなどが再ロードされると想像します。また、JVM は多数のクラスを処理できるべきではありませんか?

乾杯

ジョー

4

5 に答える 5

44

この投稿から:


この例外は、1つの単純な理由で発生しました。permgenspaceメソッド、フィールド、アノテーション、静的変数などのクラスプロパティがJava VMに格納されている場所ですが、このスペースはガベージコレクターによってクリーンアップされないという特殊性があります。 。したがって、Webアプリが多数のクラスを使用または作成する場合(動的な世代のクラスを考えています)、この問題が発生する可能性があります。これが私がこの例外を取り除くのを助けたいくつかの解決策です:

  • -XX:+CMSClassUnloadingEnabled:この設定により、permgenspaceでのガベージコレクションが有効になります
  • -XX:+CMSPermGenSweepingEnabled:ガベージコレクタがメモリからクラスを削除できるようにします
  • -XX:PermSize=64M -XX:MaxPermSize=128M:permgenspaceに割り当てられるメモリの量を増やします

これが役立つかもしれません。

2012年7月に編集(ほぼ3年後):

OndraŽižkaのコメント(そして私は上記の答えを更新しました):

JVM 1.6.0_27によると:次を使用してください:

  • CMSClassUnloadingEnabled(CMS GCを使用するときにクラスのアンロードが有効になっているかどうか)
  • CMSPermGenSweepingEnabled将来の代わりに

完全なホットスポットJVMオプション-mroeの完全なリファレンスを参照してください。

于 2009-09-20T18:29:12.023 に答える
12

実行 mvn jetty:run中にこれが表示される場合は、を設定しMAVEN_OPTSます。

Linuxの場合:

export MAVEN_OPTS="-XX:+CMSClassUnloadingEnabled -XX:PermSize=256M -XX:MaxPermSize=512M"
mvn jetty:run

Windowsの場合:

set "MAVEN_OPTS=-XX:+CMSClassUnloadingEnabled -XX:PermSize=256M -XX:MaxPermSize=512M"
mvn jetty:run

今は大丈夫なはずです。そうでない場合は、を増やし-XX:MaxPermSizeます。

これらを永続的に環境に配置することもできます。

  • exportLinuxの場合、次の行を追加します~/.bashrc

  • Windowsの場合は、を押しWin-key + PrintScreenて、に移動しAdvanced > Environmentます。http://support.microsoft.com/kb/310519も参照してください。

于 2012-07-23T01:53:54.547 に答える
3

これは、あなたが提案したようにクラスがリロードされたためです。多くのライブラリなどを使用している場合、再起動するたびにクラスの合計が急速に増加します。VisualVM で jetty インスタンスを監視して、リロード時のメモリ消費の概要を取得してください。

于 2010-09-22T17:30:28.077 に答える
2

メーリング リスト ( http://groups.google.com/group/liftweb/ ) は、Lift の公式サポート フォーラムであり、より適切な回答を得ることができます。あなたの開発セットアップの詳細はわかりませんが(詳細には触れません)、実際に再起動せずにJettyで戦争をリロードしていると思います。Lift は (上記の VonC で提案されているように) 動的なクラス生成を実行しませんが、Scala は各クロージャーを個別のクラスとしてコンパイルします。数日間にわたってコードにクロージャを追加および削除している場合、あまりにも多くのクラスがロードされ、アンロードされず、perm スペースを占有している可能性があります。上記の VonC で言及されているオプション JVM オプションを有効にして、それらが役立つかどうかを確認することをお勧めします。

于 2009-09-20T19:06:30.407 に答える
1

永続的な生成とは、JVMが、カスタムクラスローダーのように(ガベージ)収集されない可能性のあるものを配置する場所です。

デプロイする対象によっては、permgen設定を低くすることができます。一部のアプリケーションやコンテナの組み合わせにはメモリリークが含まれているため、アプリがデプロイ解除されると、クラスローダーなどが収集されず、Perm Spaceがいっぱいになり、エラーが発生することがあります。

残念ながら、現在この場合の最良のオプションは、次のjvmフラグ(192mのpermサイズの例)を使用してpermスペースを最大化することです。

-XX:MaxPermSize=192M (or 256M)

もう1つのオプションは、コンテナまたはフレームワークのいずれかがメモリをリークしないようにすることです。

于 2009-09-20T18:28:16.817 に答える