1. 概要

簡単に言うと、JVMは、オブジェクトが使用されなくなったときにメモリを解放します。 このプロセスは、ガベージコレクション( GC )と呼ばれます。

GCオーバーヘッド制限超過エラーは、 java .lang.OutOfMemoryError ファミリのエラーであり、リソース(メモリ)の枯渇を示しています。

このクイックチュートリアルでは、 java .lang.OutOfMemoryError:GC Overhead Limit Exceeded エラーの原因と、その解決方法について説明します。

2. GCオーバーヘッド制限超過エラー

OutOfMemoryError は、 java.lang.VirtualMachineErrorのサブクラスです。 これは、リソースの利用に関連する問題が発生したときにJVMによってスローされます。 より具体的には、エラーは、JVMがガベージコレクションの実行に多くの時間を費やし、ごくわずかなヒープスペースしか再利用できなかった場合に発生します。

Javaドキュメントによると、デフォルトでは、JavaプロセスがGCの実行に98 % o f以上を費やし、各実行でヒープが回復されるのが2 % o f未満の場合、JVMはこのエラーをスローするように構成されています。 つまり、これは、アプリケーションが使用可能なメモリのほぼすべてを使い果たし、ガベージコレクターがそれをクリーンアップするのに時間がかかりすぎて、繰り返し失敗したことを意味します。

この状況では、ユーザーはアプリケーションの極端な速度低下を経験します。 通常はミリ秒単位で完了する特定の操作は、完了するまでに時間がかかります。 これは、CPUがガベージコレクションに全容量を使用しているため、他のタスクを実行できないためです。

3. 動作中のエラー

java .lang.OutOfMemoryError:GC Overhead LimitExceededをスローするコードを見てみましょう。

これは、たとえば、終了していないループにキーと値のペアを追加することで実現できます。

public class OutOfMemoryGCLimitExceed {
    public static void addRandomDataToMap() {
        Map<Integer, String> dataMap = new HashMap<>();
        Random r = new Random();
        while (true) {
            dataMap.put(r.nextInt(), String.valueOf(r.nextInt()));
        }
    }
}

このメソッドが呼び出され、JVM引数が -Xmx100m -XX:+ UseParallelGC (Javaヒープサイズが100 MBに設定され、GCアルゴリズムがParallelGC)の場合、java .lang.OutOfMemoryError:GCオーバーヘッド制限がエラーを超えました。 さまざまなガベージコレクションアルゴリズムをよりよく理解するには、OracleのJavaガベージコレクションの基本チュートリアルを確認してください。

java .lang.OutOfMemoryError:プロジェクトのルートから次のコマンドを実行すると、GCオーバーヘッド制限がエラーをすぐに超えました。

mvn exec:exec

また、状況によっては、 GC Overhead LimitExceededエラーが発生する前にヒープスペースエラーが発生する場合があることにも注意してください。

4. GCオーバーヘッド制限超過エラーの解決

理想的な解決策は、メモリリークがないかコードを調べて、アプリケーションの根本的な問題を見つけることです。

これらの質問に対処する必要があります。

  • ヒープの大部分を占めるアプリケーション内のオブジェクトは何ですか?
  • これらのオブジェクトはソースコードのどの部分に割り当てられていますか?

JConsole などの自動グラフィカルツールを使用することもできます。これは、 java.lang.OutOfMemoryErrorsなどのコードのパフォーマンスの問題を検出するのに役立ちます。

最後の手段は、JVMの起動構成を変更してヒープサイズを増やすことです。

たとえば、これにより、Javaアプリケーション用に1GBのヒープスペースが提供されます。

java -Xmx1024m com.xyz.TheClassName

ただし、実際のアプリケーションコードにメモリリークがある場合、これでは問題は解決しません。 代わりに、エラーを延期します。 したがって、アプリケーションのメモリ使用量を徹底的に再評価することをお勧めします。

5. 結論

この記事では、 java .lang.OutOfMemoryError:GC Overhead LimitExceededとその背後にある理由を調べました。

いつものように、この記事に関連するソースコードはGitHubにあります。