JBossでPermGen OutOfMemoryErrorが発生する原因は何ですか?


8

JBossのPermGen OutOfMemoryErrorの根本的な原因は何ですか?

開発環境でJBoss AS 4.2.2を実行していますが、これはWebアプリケーションを何度も再デプロイした後に発生します。

Christian Vest HansenのブログにはJVMのオプションがたくさんありますが、問題は完全には解決していません。

-XX:+UseConcMarkSweepGC
-XX:+CMSPermGenSweepingEnabled
-XX:+CMSClassUnloadingEnabled
-XX:MaxPermSize=128m

回答:


5

すでに述べたように、おそらくクラスローダーのリークが発生しています。何らかの理由でクラスがアンロードされていません。これには2つの理由が考えられます

  • 上記のクラスのオブジェクトがヒープ上にまだ存在している、オブジェクトが常にそのクラスを参照している、または
  • クラスローダーはどこかで参照されていますが、何らかの理由で、クラスローダーはクラスを参照して2回ロードしないようにします

この問題に対する包括的な解決策はありません。根本原因の特定に役立つツールの1つがEclipse Memory Analyzer Toolです。これは、JVMからのヒープダンプに適用できます(-XX:+ HeapDumpOnOutOfMemoryErrorオプションを使用して、OOMのヒープダンプを有効にできます)。おそらく、Webアプリからjava.lang.Classオブジェクトを探し始め、それらが生き続けている理由を確認してください。残念ながら、PermGenは通常、JVMヒープダンプの一部ではないため、ヒープの残りの部分で相関するアーティファクトを検索することしかできません(クラスオブジェクトは、誤りがなければ、PermGenに格納されません。実際のバイトコードのみです。私が間違っているなら私を修正してください)。

HTH。

編集:
Dave Cheneyは、java.lang.Class-objectsは確かにPermGenの一部であり、通常のホットスポットヒープダンプには含まれていないとコメントで示唆しています。ヒープダンプにこの情報を書き込むJVMがない限り、別の方法が必要になります。オブジェクトのインスタンスを探すことはできますが、クラス/クラスローダーをリークしている場合(残念ながら両方とも互いに意味し合う)、他の兆候(JBossからのメタデータオブジェクトなど)を探す必要があるようです。


1
ClassオブジェクトがPermGen(つまり、Classのインスタンスであるオブジェクト)に格納されていることは確かです。Sun JVMには、コードキャッシュと呼ばれる別の領域があります。この領域には、マシンコードにコンパイルされたコードが格納されます。PermGenとコードキャッシュはどちらも、非ヒープメモリの一部であり、jconsoleなどのツールを使用して確認できます
Dave Cheney

@デイブチェイニー:あなたは正しいです。PermGenでスタックしたリークされたClassオブジェクトは通常、OPの問題の原因です。
エディ

roe、PermGenの内容はヒープダンプに書き込まれるとは思いませんが(これはSun JVMを使用しているため、他の人とはあまり経験がありません)、hprofダンプ形式は確かに次のようなことを知っています。クラスが読み込まれた、クラスローダーの数など。EclipseMemory Analyserでhprofを開くと、これがわかります。おそらく書き込まれていないのは、Javaバイトコードを構成する大きなバイナリクラスデータです。ヒープダンプに表示されるのは、PermGenに格納されているClassインスタンスの「スタブ」です。
デイブチェイニー、

2

根本的な原因は、破棄されたクラスへの参照がクラスローダーの外部にリークし、JVMがこれらのクラスをperm genからアンロードできないことです。これらのフラグを使用すると、JVM アンロードできないクラスを積極的にパージする可能性がありますが、根本的な問題は解決されません。

ここには良い、とはいえ複雑な説明があります


1

PermGen OutOfMemoryエラーの原因は、アプリの再デプロイです。根本的な原因は、再デプロイからPermGenのリークされたClassオブジェクトです。

もちろん、回避策は、特定の数の再デプロイ後にJVMを再起動することです。

これは、完全に解決するのが非常に難しい問題ですが、いくつかの調査を行うと、大きな改善を行うことができます。ここから始めましょう:Webアプリが停止しているときに、次のことを確認してください。

  • 開始したすべてのスレッドが停止します
  • 開始したすべての ThreadPoolがシャットダウンされます
  • リリースできるすべての静的参照がリリースされます

これらは、PermGenでClassオブジェクトがトラップされる原因の一部です。

また、すべてのJVM(またはすべてのバージョンのJVM)がPermGenのGCクラスオブジェクトになるわけではないことに注意してください。PermGenでGCクラスオブジェクトを実行しないJVMまたはJVMのバージョンを実行している場合、選択できるのは、特定の数の再デプロイ後にJVMを再起動することです。あなたが言及したJVMオプションを考えると、これはおそらくあなたには当てはまりません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.