1

Java スレッド プールを使用してバックグラウンドで負荷の高い処理を実行するアプリケーションがあります。

スレッドプールは、実行中に発生した例外をログに記録するように構成されています

public enum ExceptionLogger implements Thread.UncaughtExceptionHandler {
    INSTANCE;

    private static final Logger log = LoggerFactory.getLogger(ExceptionLogger.class);

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        log.error("Exception occurred at thread " + t.getName() + "\n", e);
    }
  }

私のアプリケーションのログではランダムに取得してjava.lang.OutOfMemoryError: Java heap spaceいますが、を使用してメモリ使用量をログに記録すると、Runtime.getRuntime().freeMemory()利用可能な空きヒープ領域が十分にあることがわかります。

さらに、この例外が発生した後もアプリケーションは引き続き動作します。

OutOfMemoryErrorこのメッセージを受け取る他の理由はありますか?

4

2 に答える 2

3

メモリの割り当てに失敗すると、OutOfMemoryError が発生します。

これは、次の場合に発生する可能性があります。

  • メモリが不足しています。
  • GC 回転パラメータにより、すべてのメモリを使用できなくなります。たとえば、フルでない世代の最小サイズを設定します。
  • 大きなメモリ ブロックを割り当てます。これが失敗した直後はまだ空きメモリがあり、大きなブロックを割り当てるには十分ではありません。
  • ヒープ用ではない OutOfMemoryError を取得します。たとえば、PermGen または直接メモリまたは仮想メモリ (スレッドなどの場合)
于 2012-11-07T13:03:12.550 に答える
1

Peter Lawrey の優れた回答に加えて、「GC オーバーヘッド制限に達しました」というエラーもあります。

これは、JVM がガベージ コレクションに十分な処理時間を持っていないか、GC が使用可能な合計処理能力を過度に消費している場合に発生します。CPU を大量に消費するアプリケーションと組み合わされた大量の非常に存続期間の短いオブジェクトがあり、十分な平均空きヒープ (最大ヒープ サイズ - 存続期間の長いオブジェクト) がない場合に主に発生します。

これに対する解決策はさまざまですが、多くの場合、CPU 消費量 (この場合はスレッド数) を制限したり、ヒープ サイズを増やしたりする必要があります。

于 2012-11-07T13:51:25.673 に答える