2014/06/13

java.lang.OutOfMemoryError: GC overhead limit exceeded

通常のOOMは「GCを行ったが次の処理に必要なメモリが確保できなかった場合」に発生します。しかし、このOOMは「GCを行った結果、次の処理に必要なメモリは確保できたが、処理が長い割には少ししか回収できなかった場合」に発生します(GC処理が長いだけでも回収量が少ないだけでも発生しません)。※私の経験上このOOMはFullGCが頻発した後に発生します。

オプションに

-XX:-UseGCOverheadLimit

を追加すれば、このOOMを発生させないようにする事ができます。しかし、それでも普通のOOM「Java heap space」が発生したり、そうでなくともGC時間が長すぎて処理がなかなか進まないという結果になりかねません。

結局「Java heap space」のOOMと同じで

    コマンドライン・オプションの「-Xmx」で、ヒープをより多く確保するよう指定する
    マシンの物理メモリが足りなければ増設する
    どうしても拡張できないのなら「-XX:NewRatio」や「-XX:SurvivorRatio」などで、ヒープ内部の領域を調節してうまくやりくりする(中級者以上向け)

等の対策を行う事が望ましいでしょう。

例:
JVM_HEAP="-Xms768m -Xmx768m -XX:-UseGCOverheadLimit"
JVM_DUMP="-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/heapDump"