27

CPU使用率が限界に達し、JBossを再起動する必要がある場合にこのエラーが発生しました(java.lang.OutOfMemoryError: PermGen space)。

古いJBossバージョンでを増やすための解決策を見つけましたMaxPermSize。JBoss7についても同じことが言えると思います。

二度と問題に直面しないために十分な値はどれですか?この問題を恒久的に回避する方法はありますか(たとえば、JRockitなどの別のVMを使用するなど)?

4

4 に答える 4

56

これは複数回の再デプロイ後に発生するため、一般的な種類のpermgenリークであるクラスローダーリークが発生したようです。

これらの素敵な獣は、コンテナが所有するオブジェクトから、アプリケーションクラスローダーからロードされたクラスのインスタンスであるオブジェクトへの通常の(弱ではない)参照が原因で発生します。アンデプロイ時にこれらの参照がクリアされない場合でも、アプリケーションのクラスローダーへの強力な参照チェーンが存在するため、GCを実行したり、ロードされたクラスを解放したりすることはできません。

一般的な原因は、アプリケーションクラスへの非静的参照が追加されたコンテナクラスの静的コレクションです。

JBoss AS 7のモジュールシステムには、クラスローダーのリークを防ぐためのかなり強力なプロビジョニングがあります。そのため、クラスローダーのリークをなんとかトリガーできたことに驚いています。GlassfishからAS7に移行して以来、クラスローダーのリークは発生していません。

MaxPermSizeを大きくすると、しばらく時間がかかりますが、問題を解決することはできません。

クラスローダーがリークしている理由を本当に理解する必要があります。これを行うのは「楽しい」です。あなたは税金、断続的な過失、そしてシャワーの掃除を楽しんでいますよね?リークの追跡を開始するためのいくつかのブログについては、最初のパーのリンクを参照してください。基本的に、VisualVMOQLを使用してアプリのクラスローダーへの参照を掘り下げるか、ヒープダンプを取得してjhat(JDKの一部)を使用して参照を検索する必要があります。いずれにせよ、アイデアは、アプリサーバーからアプリクラスのインスタンスを介したクラスローダーへの強力な参照チェーンがどこにあるかを把握することです。

または、アプリのコピーを取り、リークがなくなるまでアプリからビットをリッピングし始めると便利です。VisualVMまたはその他の監視をアプリサーバーVMに接続し、2回以上のデプロイ/アンデプロイサイクル後にPermGenが増加するかどうかを監視することで、リークしているかどうかを確認できます。デプロイ/アンデプロイサイクルの自動化を検討してください。アプリのごく一部やその依存関係の1つへのリークの原因を絞り込み、小さな自己完結型のテストケースを作成し、それを(a)JBossAS7のバグレポートとして送信します。これを阻止することを意味し、(b)参照を保持している犯人。

デプロイメントアーカイブ内にバンドルされている依存関係に原因を絞り込む場合は、JBossAS7モジュールに移動することで問題を解決できる場合があります。そのためのJBossモジュールを作成し、AS7のディレクトリにデプロイし、またはを介しmodulesてデプロイメントに依存関係を追加します。AS7クラスローダーのドキュメントを参照してください。Manifest.MFjboss-deployment-structure.xml

これが、プロジェクトジグソーが延期されたという事実が私を悲しませている理由です。Javaには、この雑然としたものを取り除く強力なモジュールシステムが必要です。

于 2012-07-31T07:51:03.980 に答える
8

VMパラメータは次のとおりです。

-XX:MaxPermSize=256M

限界に達しないように十分に大きくしてください。

大まかに言えば、perm genメモリは、クラスおよびインターンされた文字列に関連付けられたオブジェクトに使用されます。さまざまなクラスをたくさん使用しない限り、不足することはありません。

于 2012-07-25T09:27:21.213 に答える
4

私たちはまったく同じことをしなければなりませんでしたが、残念ながらvisualvmは私たちのために多くのことをしませんでした。

結局、Eclipseマットを使用して、クラッシュ時に生成されたヒープダンプを分析し、リークされたインスタンスがleak suspects多数あることを示すレポートを確認しました。ModuleClassLoader

[概要]タブでインスタンスの1つをクリックし、[ merge shortest paths to GC roots+ ]を選択するとexclude weak references、これらのModuleClassLoaderインスタンスをGCすることができなかった原因がわかりました。

https://smalldata.tech/blog/2015/09/29/detecting-java-permgen-memory-leak

于 2015-09-29T14:02:15.023 に答える
2

なぜそれが起こるのですか?

「PermGen」エラーは、Java仮想マシンが永続世代のメモリを使い果たしたときに発生します。Javaには、エデン、ヤング、オールド、パーマネントの4世代の世代別ガベージコレクターがあることを思い出してください。エデン世代では、オブジェクトは非常に短命であり、ガベージコレクションは迅速かつ頻繁に行われます。若い世代は、エデン世代を生き残った(または割り当て時にエデン世代がいっぱいだったために若い世代にプッシュダウンされた)オブジェクトで構成され、若い世代のガベージコレクションはそれほど頻繁ではありませんが、それでもかなり定期的に行われます(アプリケーションは実際に何かを実行し、時々オブジェクトを割り当てます)。古い世代、まあ、あなたはそれを理解しました。若い世代を生き延びた、または押し下げられたオブジェクトが含まれています、ガベージコレクションの頻度はさらに低くなりますが、それでも発生する可能性があります。そして最後に、恒久的な世代。これは、仮想マシンが永遠の命を支持することを決定したオブジェクト用です。これはまさに問題の核心です。永続世代のオブジェクトがガベージコレクションされることはありません。つまり、通常の状況では、jvmが通常のコマンドラインパラメータで起動されます。したがって、Webアプリケーションを再デプロイすると、WARファイルが解凍され、そのクラスファイルがjvmにロードされます。そして、これが重要です。ほとんどの場合、永続的な世代になります...(以下から取得)これは、仮想マシンが永遠の命を支持することを決定したオブジェクト用です。これはまさに問題の核心です。永続世代のオブジェクトがガベージコレクションされることはありません。つまり、通常の状況では、jvmが通常のコマンドラインパラメータで起動されます。したがって、Webアプリケーションを再デプロイすると、WARファイルが解凍され、そのクラスファイルがjvmにロードされます。そして、これが重要です。ほとんどの場合、永続的な世代になります...(以下から取得)これは、仮想マシンが永遠の命を支持することを決定したオブジェクト用です。これはまさに問題の核心です。永続世代のオブジェクトがガベージコレクションされることはありません。つまり、通常の状況では、jvmが通常のコマンドラインパラメータで起動されます。したがって、Webアプリケーションを再デプロイすると、WARファイルが解凍され、そのクラスファイルがjvmにロードされます。そして、これが重要です。ほとんどの場合、永続的な世代になります...(以下から取得)WARファイルが解凍され、そのクラスファイルがjvmにロードされていること。そして、これが重要です。ほとんどの場合、永続的な世代になります...(以下から取得)WARファイルが解凍され、そのクラスファイルがjvmにロードされていること。そして、これが重要です。ほとんどの場合、永続的な世代になります...(以下から取得) http://rlogiacco.blogspot.com/2009/02/jboss-and-permgen-outofmemoryerror.html

ここにいくつかのアドバイスがあります:

JVMにこのパラメーターを使用します。それらは、ガベージコレクターにPermGenでもそのアルゴリズムを呼び出すように指示します。

set JAVA_OPTS=-Xms512m -Xmx1024m 
-XX:PermSize=512m 
-XX:MaxPermSize=1024m 
-XX:+UseConcMarkSweepGC 
-XX:+CMSPermGenSweepingEnabled 
-XX:+CMSClassUnloadingEnabled 
  • CMSPermGenSweepingEnabled設定には、ガベージコレクションの実行にPermGenが含まれています。デフォルトでは、PermGenスペースがガベージコレクションに含まれることはありません(したがって、無制限に拡張されます)。
  • CMSClassUnloadingEnabled設定は、 PermGenガベージコレクションスイープにクラスオブジェクトに対してアクションを実行するように指示します。デフォルトでは、ガラベージコレクション中にPermGenスペースにアクセスしている場合でも、クラスオブジェクトは免除されます。

アプリケーションをデプロイするたびにPermGenのデータ量が増えるため、JBOSSを再起動します。

SunJVMの代わりにJRocketJVMを使用することもできます。ガベージコレクタアルゴリズムにPermGenがありません。

于 2016-10-25T10:26:35.287 に答える