web-dev-qa-db-ja.com

リフトと桟橋に関するPermGenの問題

私は標準のLiftプラットフォーム(Mavenと桟橋)で開発しています。私はこれを繰り返し(数日に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は多数のクラスを処理できるべきではありませんか?

乾杯

ジョー

41
Joe

から この投稿

この例外は、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の代わりに

Mroeについては、完全な Hotspot JVMオプション-完全なリファレンス を参照してください。

44
VonC

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を増やします。

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

  • Linuxの場合、export行を~/.bashrcに追加します

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

12
Ondra Žižka

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

3
col

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

2
Jorge Ortiz

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

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

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

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

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

1
Miguel Ping