Develop with pleasure!

福岡でCloudとかBlockchainとか。

java.lang.OutOfMemoryError: GC overhead limit exceeded

Javaなエンジニアであればお馴染みのOutOfMemoryError。
こないだ単体テストを全件流してたら途中で

java.lang.OutOfMemoryError: GC overhead limit exceeded

が発生。お馴染みのOutOfMemoryErrorかと思ったけどメッセージに「GC overhead limit exceeded」とある。
いつもの「Java heap space」とかいうメッセージじゃないので気になって調べてみる。

この「GC overhead limit exceeded 」は、HotSpot VMの1.6からデフォルトで有効になったポリシーで、ヒープ領域が不足する前に早期に潜在的なOutOfMemoryErrorの検出するために導入された模様。このポリシーはGCの経過時間と頻度が基準になってて、経過時間が長かったり頻繁にFull GCが発生するようなケースがトリガーになる。

Oracleの公式ドキュメントより

The parallel collector will throw an OutOfMemoryError if too much time is being spent in garbage collection: if more than 98% of the total time is spent in garbage collection and less than 2% of the heap is recovered, an OutOfMemoryError will be thrown. This feature is designed to prevent applications from running for an extended period of time while making little or no progress because the heap is too small. If necessary, this feature can be disabled by adding the option -XX:-UseGCOverheadLimit to the command line.

Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning

ざっと意訳すると
parallel GC や conccurent GC のコレクターがOutOfMemoryErrorを投げる条件は

  • 総時間の98%以上がGCに費やされている

かつ

  • 改修されたヒープが2%未満の

の場合。

この機能はアプリケーションが、ヒープが小さすぎるために長時間渡って処理が進まないままになるといった状態に陥ることを回避する目的で設計されてる。もしこの機能が必要なければJVMのオプションに「-XX:-UseGCOverheadLimit」を指定することで機能自体を無効にできる。


まぁJVMがハングアップするのを防いで、VMのヒープダンプやスレッドダンプを収集する時間が取れるので無効にする意味は無さげ。