OutOfMemoryError:GCオーバーヘッド制限を超えました

OutOfMemoryError:GCオーバーヘッド制限を超えました

1. 概要

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

GC Overhead Limit Exceededエラーは、java.lang.OutOfMemoryErrorファミリーのエラーであり、リソース(メモリ)の枯渇を示しています。

この簡単な記事では、java.lang.OutOfMemoryError: GC Overhead Limit Exceededエラーの原因とその解決方法について説明します。

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

OutOfMemoryErrorjava.lang.VirtualMachineErrorのサブクラスです。リソースの利用に関連する問題が発生すると、JVMによってスローされます。 より具体的には、the error occurs when the JVM spent too much time performing Garbage Collectionであり、ヒープスペースをほとんど再利用できませんでした。

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

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

3. アクションのエラー

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

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

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

このメソッドが呼び出され、-Xmx100m -XX:+UseParallelGC (Javaヒープサイズが100MBに設定され、GCアルゴリズムがParallelGC)であるJVM引数を使用すると、java.lang.OutOfMemoryError: GC Overhead Limit Exceededエラーが発生します。 さまざまなガベージコレクションアルゴリズムをよりよく理解するために、OracleのJava Garbage Collection Basicsチュートリアルを確認できます。

projectのルートから次のコマンドを実行すると、java.lang.OutOfMemoryError: GC Overhead Limit Exceededエラーがすぐに発生します。

mvn exec:exec

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

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

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

次の質問に対処する必要があります。

  • ヒープの大部分を占めるアプリケーション内のオブジェクトは何ですか?

  • これらのオブジェクトは、ソースコードのどの部分に割り当てられていますか?

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

最後の手段は、JVM起動構成を変更してヒープサイズを増やすことです。 たとえば、これにより、Javaアプリケーションに1GBのヒープスペースが与えられます。

java -Xmx1024m com.xyz.TheClassName

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

5. 結論

このチュートリアルでは、java.lang.OutOfMemoryError: GC Overhead Limit Exceededとその背後にある理由を調べました。

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