OOM エラーに出くわしたのですが、よく発生する Heap 領域のものとは違うエラーが発生しました:
java.lang.OutOfMemoryError: PermGen space
Hive 関係のアプリケーションで発生していて、temporary function を大量に利用する処理を入れたばかりだったので、temporary function によって読み込まれた JAR とクラスがこの PermGen 領域に加わり、OOM エラーが発生したようです。
PermGen の理解
"PermGen" の正確な理解が怪しかったので少し調べたところ、とても詳しく解説されているブログがありました:
PermGen 領域 HotSpot VM で利用されますが、通常のヒープ領域とは別に確保され、クラスやメソッドのデータ、及びそのメタデータが格納されるとあります。領域の拡張も -XX:PermSize
や -XX:MaxPermSize
オプションなどで、ヒープ領域とは別に設定する必要があります。
jmap コマンドで稼働しているプロセスのメモリ情報が取得出来るので、今回はこれで PermGen に割り当てられているメモリ容量を確認して、-XX:MaxPermSize
オプションで容量拡張しました。
$ sudo jmap -heap <プロセスID>
Java8 では PermGen -> Metaspace
この jmap コマンドですが、Java SE 8 で実行すると、以下のような結果になります:
$ sudo jmap -heap <プロセスID> ... Heap Configuration: MinHeapFreeRatio = 0 MaxHeapFreeRatio = 100 MaxHeapSize = 1073741824 (1024.0MB) NewSize = 22020096 (21.0MB) MaxNewSize = 357564416 (341.0MB) OldSize = 45088768 (43.0MB) NewRatio = 2 SurvivorRatio = 8 MetaspaceSize = 21807104 (20.796875MB) CompressedClassSpaceSize = 1073741824 (1024.0MB) MaxMetaspaceSize = 17592186044415 MB G1HeapRegionSize = 0 (0.0MB) Heap Usage: ...
PermGen
という言葉が見つからないのですが、Java8 では "Naive メモリ" という領域へ移動し、名前も Metaspace という名前に変更されています。これを詳しく解説されているブログがありました:
もやは -XX:MaxPermSize
などの PermGen に関するオプションは意味がないようですが、デフォルトでは Metaspace には容量制限が実質ない状態なので、MaxMetaspace
オプションを指定していなければ、今回のような OOM は発生しなさそうです。