903

JUnitテストを実行すると、次のエラー メッセージが表示されます。

java.lang.OutOfMemoryError: GC overhead limit exceeded

が何であるかは知っていますOutOfMemoryErrorが、GC オーバーヘッド制限とはどういう意味ですか? どうすればこれを解決できますか?

4

22 に答える 22

828
于 2009-09-08T11:39:14.837 に答える
237

Oracle の記事「Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning」からの引用:

過剰な GC 時間と OutOfMemoryError

ガベージ コレクションに費やされた時間が長すぎる場合、パラレル コレクターは OutOfMemoryError をスローします。総時間の 98% 以上がガベージ コレクションに費やされ、回復されたヒープが 2% 未満の場合、OutOfMemoryError がスローされます。この機能は、ヒープが小さすぎるためにアプリケーションがほとんどまたはまったく進行していない状態で長時間実行されるのを防ぐように設計されています。-XX:-UseGCOverheadLimit必要に応じて、コマンド ラインにオプションを追加して、この機能を無効にすることができます。

編集:誰かが私よりも速く入力できるようです:)

于 2009-09-08T11:43:16.310 に答える
103

プログラムにメモリ リークがないことが確実な場合は、次のことを試してください。

  1. たとえば、ヒープ サイズを増やします-Xmx1g
  2. コンカレント低ポーズ コレクターを有効にし-XX:+UseConcMarkSweepGCます。
  3. 可能な場合は既存のオブジェクトを再利用して、メモリを節約します。

必要に応じて、コマンド ラインにオプションを追加して制限チェックを無効にすることができます。-XX:-UseGCOverheadLimit

于 2011-12-14T01:44:17.533 に答える
53

通常はコードです。簡単な例を次に示します。

import java.util.*;

public class GarbageCollector {

    public static void main(String... args) {

        System.out.printf("Testing...%n");
        List<Double> list = new ArrayList<Double>();
        for (int outer = 0; outer < 10000; outer++) {

            // list = new ArrayList<Double>(10000); // BAD
            // list = new ArrayList<Double>(); // WORSE
            list.clear(); // BETTER

            for (int inner = 0; inner < 10000; inner++) {
                list.add(Math.random());
            }

            if (outer % 1000 == 0) {
                System.out.printf("Outer loop at %d%n", outer);
            }

        }
        System.out.printf("Done.%n");
    }
}

Windows 7 32 ビットで Java 1.6.0_24-b07 を使用しています。

java -Xloggc:gc.log GarbageCollector

次に、見てくださいgc.log

  • BADメソッドで444回発動
  • WORSEメソッドで666回発動
  • BETTER メソッドを使用して 354 回トリガーされました

確かに、これは最良のテストや最良の設計ではありませんが、そのようなループを実装するしかない状況に直面した場合、または動作が悪い既存のコードを処理する場合、新しいオブジェクトを作成する代わりにオブジェクトを再利用することを選択すると、ガベージコレクターが邪魔する回数...

于 2011-04-12T19:27:01.417 に答える
31

このオプションを設定して、ヒープサイズを少し増やしてください。

実行 → 実行構成 → 引数 → VM 引数

-Xms1024M -Xmx2048M

Xms - 最小制限

Xmx - 上限

于 2014-05-13T10:40:23.373 に答える
13

私にとっては、次の手順が機能しました。

  1. eclipse.iniファイルを開く
  2. 変化する

    -Xms40m
    -Xmx512m
    

    -Xms512m
    -Xmx1024m
    
  3. エクリプスを再起動する

こちらをご覧ください

于 2014-12-31T05:09:49.350 に答える
12

以下は私のために働いた。次のスニペットを追加するだけです。

android {
        compileSdkVersion 25
        buildToolsVersion '25.0.1'

defaultConfig {
        applicationId "yourpackage"
        minSdkVersion 10
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
    }
dexOptions {
        javaMaxHeapSize "4g"
    }
}
于 2016-12-27T11:47:41.483 に答える
6

gradle.propertiesこれをファイルに追加することで、メモリ割り当てとヒープ サイズを増やすこともできます。

org.gradle.jvmargs=-Xmx2048M -XX\:MaxHeapSize\=32g

2048M と 32g である必要はありません。好きなだけ大きくしてください。

于 2019-07-23T21:03:58.610 に答える
0

Jdeveloper のsetDomainEnv.cmdでメモリ サイズを増やす必要があります。

set WLS_HOME=%WL_HOME%\server    
set XMS_SUN_64BIT=**256**
set XMS_SUN_32BIT=**256**
set XMX_SUN_64BIT=**3072**
set XMX_SUN_32BIT=**3072**
set XMS_JROCKIT_64BIT=**256**
set XMS_JROCKIT_32BIT=**256**
set XMX_JROCKIT_64BIT=**1024**
set XMX_JROCKIT_32BIT=**1024**

if "%JAVA_VENDOR%"=="Sun" (
    set WLS_MEM_ARGS_64BIT=**-Xms256m -Xmx512m**
    set WLS_MEM_ARGS_32BIT=**-Xms256m -Xmx512m**
) else (
    set WLS_MEM_ARGS_64BIT=**-Xms512m -Xmx512m**
    set WLS_MEM_ARGS_32BIT=**-Xms512m -Xmx512m**
)

set MEM_PERM_SIZE_64BIT=-XX:PermSize=**256m**
set MEM_PERM_SIZE_32BIT=-XX:PermSize=**256m**

if "%JAVA_USE_64BIT%"=="true" (
    set MEM_PERM_SIZE=%MEM_PERM_SIZE_64BIT%
) else (
    set MEM_PERM_SIZE=%MEM_PERM_SIZE_32BIT%
)

set MEM_MAX_PERM_SIZE_64BIT=-XX:MaxPermSize=**1024m**
set MEM_MAX_PERM_SIZE_32BIT=-XX:MaxPermSize=**1024m**
于 2016-04-13T09:52:39.197 に答える
0

@Buhbメインメソッド内の通常のスプリングブートWebアプリケーションでこれを再現しました。コードは次のとおりです。

public static void main(String[] args) {
    SpringApplication.run(DemoServiceBApplication.class, args);
    LOGGER.info("hello.");
    int len = 0, oldlen=0;
    Object[] a = new Object[0];
    try {
        for (; ; ) {
            ++len;
            Object[] temp = new Object[oldlen = len];
            temp[0] = a;
            a = temp;
        }
    } catch (Throwable e) {
        LOGGER.info("error: {}", e.toString());
    }
}

来る原因となったサンプル コードも oracle java8 言語仕様からのものです。

于 2021-09-11T05:17:23.433 に答える