Java Hibernateとglassfishサーバーを使用するWebアプリケーションを実行しています。
Java.lang.OutOfMemoryError: PermGen space
数回展開した後の例外。
私は試した -XX:MaxPermSize=128M
私の環境変数で、しかしそれは動作しません。
これはクラスローダーのメモリリークです。アプリケーションを再デプロイするたびに、新しいクラスローダーが作成され、アプリケーションのすべてのクラスが再びロードされます。これは、perm genスペースのメモリーを消費します。
古いクラスローダーとそのすべてのロードされたクラスはガベージコレクションする必要があります。そうしないと、複数回デプロイした後に最終的にPermGenスペースOOMEに遭遇します。外部クラスローダーによってロードされたオブジェクトが古いクラスローダーによってロードされたオブジェクトへの参照を保持している場合、これは機能しません。 この記事 は、問題の適切な説明を提供します。
一般的に、クラスローダーのリークは分析が困難であり、修正が難しい場合があります。古いクラスローダーがガベージコレクションされない理由を調べるには、プロファイラーを使用する必要があります。 JProfiler では、ヒープウォーカーを使用し、glassfishクラスローダーオブジェクトを選択し、受信参照ビューを使用して、ガベージコレクタールートへのパスを確認します。
クラスローダークラスはorg.Apache.servlet.jasper.JasperLoader
と呼ばれます。これは、クラスローダーがロードされたオブジェクトのライブインスタンスによってのみ保持される、通常の状況のスクリーンショットです。
あなたの状況では、外部オブジェクトからの参照が表示されるはずです。 Webコンテナーでのクラスローダーリークのもう1つの一般的な原因は、停止しないバックグラウンドスレッドです。たとえば、Google Guiceには3.0でこのようなバグがあります。
(免責事項:私の会社はJProfilerを開発しています)
この問題を解決するには(LinuxベースのOSで)次のようにします
1)メモリを増やす(この問題が頻繁に発生しないように)で「domain.xml」を設定する
/ glassfish/domain/domain1/config
検索する
<jvm-options>-XX:MaxPermSize=
set it to higher value eg- 198m or 256m
2)glassfishプロセスを強制終了して、実行していたポートを解放します(私の場合は8686)ターミナルを開き(LinuxベースのOSで)、タイプします-
Sudo netstat -npl | grep 8686
これは次のような結果になります。
tcp6 0 0 :::8686 :::* LISTEN 3452/Java
次の使用
kill -9 3452
そのプロセスを強制終了する(この場合は3452)
さあ、glassfishを起動してみてください。起動するはずです。
Windowsを使用している場合は、タスクマネージャーでglassfishプロセス(Java.exe * 32)を強制終了してから、サーバーを再起動してください。
この問題は、反復展開で何度も発生します。私はこれに何度も直面しています。 glassfishのバグについては、以下のJIRAリンクを参照してください。