OutOfMemoryErrorの系列(3):Permgenスペース
HTTPS:// blog.csdn.net/renfufei/article/details/77994177
説明:Permgen(永久世代)の概念とJDK1.7以前のバージョンに属し、Javaプログラムの発展に適応するために、JDK8以降のバージョンの使用制限の少ないメタスペースではなく、次の記事を参照してください。 OutOfMemoryErrorのシリーズ(4) :メタスペース。
これは、このシリーズの第三の記事、関連する記事の一覧です。
- OutOfMemoryErrorの系列(1):Javaのヒープスペース
- OutOfMemoryErrorの系列(2):GCオーバーヘッド制限を超え
- OutOfMemoryErrorの系列(3):Permgenスペース
- OutOfMemoryErrorの系列(4):メタスペース
JVMは、Javaプログラムが起動パラメータによって構成することができる最大メモリ使用量を制限します。下に示すように、Javaヒープメモリは、複数の領域に分割されます。
JVM起動パラメータによって、これらの領域の最大値、 -Xmx
および -XX:MaxPermSize
指定されました。指定されない場合、それは、オペレーティング・システム・プラットフォームと物理メモリのサイズに応じて決定されます。
java.lang.OutOfMemoryErrorを:PermGen空間 意味表現エラーメッセージがある:パーマネント(Permanent世代)のメモリ領域を置換することは完全です
原因分析
さんがPermGenを見に行ってまで使用されてみましょう。
JDK1.7以前では、永久的な置換(永久世代)には、主にクラス名(名前)、フィールド(フィールド)、メソッド(メソッド)及びバイトコードを含むクラス定義をロード/キャッシュメモリに格納するために使用されます(メソッドのバイトコード)と、定数プール(定数プール情報);クラスオブジェクト配列(対象配列)/関連配列型(型配列)、ならびにJITコンパイラ最適化クラス情報。
簡単に確認することができ、かつPermGen JVMクラスの量は、メモリの量/サイズにロードされます。言うことができる PermGenスペース:java.lang.OutOfMemoryErrorを主な理由は、あまりにも大きすぎるまたはメモリ容量にロードされたクラスの数です。
例
最も単純な例
私たちは、PermGenスペースの使用は、JVMがロードされたクラスの数との素晴らしい関係を持っていることを知っています。次のコードは、このことを示しています。
import javassist.ClassPool;
public class MicroGenerator { public static void main(String[] args) throws Exception { for (int i = 0; i < 100_000_000; i++) { generate("eu.plumbr.demo.Generated" + i); } } public static Class generate(String name) throws Exception { ClassPool pool = ClassPool.getDefault(); return pool.makeClass(name).toClass(); } }
forループ内のコード、動的に生成されたクラスがたくさん。これは、使用して見ることができ Javassistの クラスは非常に単純で生成するツールを。
その後、スロー、Permgenスペースを埋めるだろう、新しいクラスの多くを生成し、より多く生成されたクラスとして、メモリにロードされます。このコードを実行し Permgenスペース:java.lang.OutOfMemoryErrorを 、当然のことながら、エラーを、OutOfMemoryErrorのスローの他のタイプが存在してもよいです。
:すぐに効果を見るために、次のような適切なJVM起動パラメータを追加することができます -Xmx200M -XX:MaxPermSize=16M
ようにと。
生成されたときのOutOfMemoryError再配備
注:Tomcatの開発に警告した場合、無視することができます。本番環境は、あなたがゼロからスタートすることができ、直接オフ/またはキル関連のJVM、再デプロイをお勧めしません。
再デプロイするWebアプリケーションは、それが引き起こす可能性がある場合は、次のシナリオでは、より一般的です PermGenスペース:java.lang.OutOfMemoryErrorを 。エラーは、再デプロイ、Tomcatのコンテナは、新しいクラスをロードするために新しいクラスローダを使いたい理由に立って、聞かせてガベージコレクタ クラスローダの前にクリーンアウト(ロードされたクラスと一緒に一緒に)なります。
しかし、現実には、このようなスレッド、JDBCドライバ、およびファイルシステムのハンドル(取っ手)として楽観的、多くのサードパーティのライブラリ、およびリソースの一部の限られた共有、ではないかもしれないが、クラスローダをリードする前に完全にアンインストールすることはできません。だから、とき再デプロイ、クラスがまだPermGenに常駐する前に、それぞれが、再デプロイMBの数十にごみのMBの数百を持っています。
駆動負荷JDBCデータベースの初期化コードを介して接続されたアプリケーションの起動を仮定する。JDBCスペックドライバを用いてそれ自体を登録する のjava.sql.DriverManagerに追加され、それ自体のインスタンスである、(インスタンス) のDriverManager 静的にドメイン。
だから、アプリケーションがコンテナからアンロードされるときに、 のjava.sql.DriverManagerは JDBCドライバの別のインスタンスを保持しながら、依然としてJDBC例(Tomcatはしばしば警告)を保持し、 はjava.lang.Classloaderの インスタンスを、 ガベージコレクタは 、またに方法はありません対応するメモリ空間を回復します。
java.lang.ClassLoaderのは 、すべてのクラスの例はその負荷、メモリのMBの通常数十/数百を保持しています。私たちは、それはいくつかの再デプロイ後に、それが原因となります、PermGenスペースの再デプロイの大きさについての別の部分を取るだろう、見ることができます PermGenスペース:java.lang.OutOfMemoryErrorを 使用すると、関連するエラー・メッセージが表示されます、ログファイルにエラーを。
ソリューション
プログラムが起動し、生成1.解決のOutOfMemoryError
エラーが発生した場合、プログラムの開始は、OutOfMemoryErrorが発生PermGenが枯渇すると、そのクラスをロードするために、より多くのメモリを変更することができます持っているプログラムのサイズを大きくPermGenを解決するために非常に簡単です。.. -XX:MaxPermSizeを 以下のように起動時のパラメータ:
java -XX:MaxPermSize=512m com.yourcompany.YourClass
最大構成は、JVMがPermGenを使用するためのより多くのスペースができます 512MB
十分でない場合、スローされます、 OutOfMemoryErrorが発生します。
2. OutOfMemoryErrorが再デプロイを解決するために生成しました
私たちは、ダンプ分析(ヒープダンプ解析)をヒープできます - 再デプロイした後、ダンプヒープを実行し、次のよう:
jmap -dump:format=b,file=dump.hprof <process-id>
次に、ダンプヒープ・ダンプ・アナライザ(例えば、強力なEclipseのMAT)によって得られたファイルを読み込みます。重複したクラス、クラスに対応し、特にクラスローダ(クラスローダー)を検索します。あなたは現在使用中のものを見つけるために、すべてのクラスローダを比較したいことがあります。
EclipseのMATは、各プラットフォーム上で独自のインストールパッケージを持っている公式サイトのアドレス:.ダウンロードし、約50MB程度です Http://www.eclipse.org/mat/downloads.phpを
クラスローダは、(非アクティブクラスローダー)を使用していないために、あなたはへの最短パスを決定する必要が GCルートを されてからそれを防ぐかを確認するために、 ガベージコレクタ に回復した。問題の根本を見つけるために。原因は、サードパーティのライブラリである場合には、あなたが解決策を見つけるためにGoogle / StackOverflowのを検索することができます。問題は、独自のコードである場合は、関連する参照を解放するために適切なタイミングで必要になります。
3.決意OutOfMemoryErrorが発生したランタイム
OutOfMemoryErrorの動作中に発生した場合、それは最初に確認する必要がある GCがPermGenクラスからアンロードするかどうか。この分野での公式JVMは、(クラスをロードした後、クラスは使用されなくなった場合でも、メモリに常駐することが許されていない)は非常に保守的である。しかし、運転中に近代的なアプリケーションは、動的の多くを作成し、クラスは基本的に非常に短いライフサイクルであるクラスは、JVMの古いバージョンでは非常によく、それらに対処することはできません。その後、我々はアンクラスにJVMを許可する必要があります。以下の起動パラメータを使用します。
-XX:+CMSClassUnloadingEnabled
デフォルトでは CMSClassUnloadingEnabled 値をfalse
、明示的に指定する必要があるので、。有効にすると、 GCはクリーンアップされます PermGen、アンインストール不要なクラスを。もちろん、このオプションは設定されている UseConcMarkSweepGCをする テイク効果を。もし ParallelGC、または シリアルGC あなたがに切り替える必要がCMS:
-XX:+UseConcMarkSweepGC
それはアンインストールすることができると判断クラスである場合、そこにOutOfMemoryErrorがあれば、それは次のコマンドに似ているヒープ・ダンプ分析を、必要があるでしょう:
jmap -dump:file=dump.hprof,format=b <process-id>
次いで、分析器(例えば、EclipseのMAT)によってヒープダンプヒープ・ダンプをロードします。最も重いを見つけるクラスローダは、クラスローダよりもクラスのインスタンスの数及び対応する負荷によって最もロードされたクラスの数が最も前方の部分を識別することで、一つ一つを分析しました。
クラスごとに手動で問題を見つけるために、生成されたクラスコードを追跡する必要があるため、疑われます。
さらに読書: OOMで:Permgenは言うさようなら
オリジナルリンク: https://plumbr.eu/outofmemoryerror/permgen-space
翻訳発売日:2017年8月28日