Javaで「java.lang.OutOfMemoryError: PermGen space」の例外が発生した場合は、JVM(Java Virtual Machine)のメモリ管理領域である「Permanent領域」が不足した場合に発生する例外になります。
「Permanent領域」とは、JVMがクラス、メソッド情報などのロードした情報を保持している領域です。
今回は、「Permanent領域」が不足した場合の対応方法、 「Permanent領域」のメモリ領域の確認方法についての解説をしていきます。
環境
検証に使用した実行環境を以下に記載します。
- Java:7
「Permanent領域」が不足した場合の対応方法について
「Permanent領域」が不足した場合の対応方法は、おもに以下に記載する2種類があります。
- ロードするクラスなどを減らす。
- JVMの起動オプションに「Permanent領域」を指定する。
基本的には「2.」を選択することが多いと思います。「1.」はクラスを選別して削除する必要があります。必要かどうかの選別を確実に行える場合は、こちらの対応方法でもよいと思います。
「Permanent領域」の拡張方法について
「Permanent領域」の拡張方法は、JVMの起動オプションとして以下に記載する内容を指定します。
起動オプション名 | オプションの機能 |
---|---|
-XX:PermSize | 「Permanent領域」の初期値を指定します。 64MBを指定する場合は、「-XX:PermSize=64m」になります。 |
-XX:MaxPermSize | 「Permanent領域」の最大値を指定します。 64MBを指定する場合は、「-XX:PermSize=64m」になります。 |
起動オプションを指定して実行する場合は、以下に記載するような内容になります。
java -XX:PermSize=128m -XX:MaxPermSize=128m xxxx
【注意】
Javaのバージョン「8」以降では、JVMのメモリ管理方法の変更されています。このため、この方法で指定した場合は、以下に記載する警告が表示されて設定値も無視されますので注意してください。
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=128M; support was removed in 8.0 Java HotSpot(TM) 64-Bit Server VM warning: ignoring option MaxPermSize=128M; support was removed in 8.0
Javaのバージョン「8」以降では、以下に記載する方法で指定してください。
- -XX:MetaspaceSize
- -XX:MaxMetaspaceSize
「Permanent領域」のメモリ領域の確認方法について
「Permanent領域」のメモリ領域の確認方法については、「JDK(Java Development Kit)」のインストール時に付属しているツールを使用します。「Permanent領域」のメモリ確認するためには、以下に記載する2つのツールを使用します。
- jps
- jstat
【注意】
表示や使用できる情報は、 ツールを実行したユーザーがアクセス可能なJVMだけになります。例えば、管理者権限でJVMが存在している場合は、一般ユーザー権限の状態でツールを実行しても表示されず、使用することもできないため注意してください。
jps
「jps」は、JVMの一覧を表示するツールです。ここで取得した情報を「jstat」で使用します。
使用方法
使用方法の例を以下に記載します。ここで、出力された数字を「jstat」で使用します。また、実行環境により数字は異なります。
$ jps 1264 Jps
その他の使用方法は、「こちら」を確認してください。
jstat
「jstat」は、JVMの統計情報を確認するためのツールです。いろいろなオプションにより確認対象を変更することができます。
使用方法
使用方法の例を以下に記載します。 今回は、「Permanent領域」に関連する情報を確認するため「-gcold」オプションを指定して実行します。
$ jstat -gcold JVM識別子 間隔
「JVM識別子」は、「jps」で取得した数字を指定してください。
「間隔」は、ミリ秒になります。秒単位で指定したい場合は、「s」を設定してください。「1秒」を指定したい場合は「1000 = 1000m = 1s」のいずれかのように指定します。
その他の使用方法は、「こちら」を確認してください。
出力内容の確認方法
確認を始めると以下のような情報が出力されます。
PC PU OC OU YGC FGC FGCT GCT 65536.0 65497.3 524288.0 0.0 30 0 0.000 2.203 65536.0 65497.5 524288.0 0.0 30 0 0.000 2.203
出力された内容の意味は以下のようになります。今回は、「Permanent領域」を確認するため「PC」と「PU」に注目します。
列 | 説明 |
---|---|
PC | Permanent領域の現在の容量(KB) |
PU | Permanent領域の使用率(KB) |
OC | Old領域の現在の容量(KB) |
OU | Old領域の使用率(KB) |
YGC | 若い世代のGCイベント数 |
FGC | フルGCイベント数 |
FGCT | フルガベージコレクション時間 |
GCT | ガベージコレクション総時間 |
「PC」が現在の「Permanent領域」になります。これが不足している場合は、「-XX:MaxPermSize」で指定した容量まで拡張することができます。
「PU」が現在の「Permanent領域」の使用率になります。プログラムを実行していると少しずつこの使用率が増えていきます。不足した場合は、GC(ガベージコレクション)が動作して使用率をさげる動作が行われます。GCが動作しても不足した場合は、今回の問題である「java.lang.OutOfMemoryError」にて「PermGen space」が発生することになります。
まとめ
「java.lang.OutOfMemoryError」にて「PermGen space」が発生した場合は、「Permanent領域」が不足したことが原因により発生します。対処方法は以下の2点になります。
- 「Permanent領域」を使用するクラスなどの情報を減らす。
- JVM実行時のオプションに「-XX:MaxPermSize」を設定する。