JUnit
テストを実行すると、次のエラー メッセージが表示されます。
java.lang.OutOfMemoryError: GC overhead limit exceeded
が何であるかは知っていますOutOfMemoryError
が、GC オーバーヘッド制限とはどういう意味ですか? どうすればこれを解決できますか?
JUnit
テストを実行すると、次のエラー メッセージが表示されます。
java.lang.OutOfMemoryError: GC overhead limit exceeded
が何であるかは知っていますOutOfMemoryError
が、GC オーバーヘッド制限とはどういう意味ですか? どうすればこれを解決できますか?
Oracle の記事「Java SE 6 HotSpot[tm] Virtual Machine Garbage Collection Tuning」からの引用:
過剰な GC 時間と OutOfMemoryError
ガベージ コレクションに費やされた時間が長すぎる場合、パラレル コレクターは OutOfMemoryError をスローします。総時間の 98% 以上がガベージ コレクションに費やされ、回復されたヒープが 2% 未満の場合、OutOfMemoryError がスローされます。この機能は、ヒープが小さすぎるためにアプリケーションがほとんどまたはまったく進行していない状態で長時間実行されるのを防ぐように設計されています。
-XX:-UseGCOverheadLimit
必要に応じて、コマンド ラインにオプションを追加して、この機能を無効にすることができます。
編集:誰かが私よりも速く入力できるようです:)
プログラムにメモリ リークがないことが確実な場合は、次のことを試してください。
-Xmx1g
。 -XX:+UseConcMarkSweepGC
ます。必要に応じて、コマンド ラインにオプションを追加して制限チェックを無効にすることができます。-XX:-UseGCOverheadLimit
通常はコードです。簡単な例を次に示します。
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
確かに、これは最良のテストや最良の設計ではありませんが、そのようなループを実装するしかない状況に直面した場合、または動作が悪い既存のコードを処理する場合、新しいオブジェクトを作成する代わりにオブジェクトを再利用することを選択すると、ガベージコレクターが邪魔する回数...
このオプションを設定して、ヒープサイズを少し増やしてください。
実行 → 実行構成 → 引数 → VM 引数
-Xms1024M -Xmx2048M
Xms - 最小制限
Xmx - 上限
私にとっては、次の手順が機能しました。
eclipse.ini
ファイルを開く変化する
-Xms40m
-Xmx512m
に
-Xms512m
-Xmx1024m
エクリプスを再起動する
以下は私のために働いた。次のスニペットを追加するだけです。
android {
compileSdkVersion 25
buildToolsVersion '25.0.1'
defaultConfig {
applicationId "yourpackage"
minSdkVersion 10
targetSdkVersion 25
versionCode 1
versionName "1.0"
multiDexEnabled true
}
dexOptions {
javaMaxHeapSize "4g"
}
}
gradle.properties
これをファイルに追加することで、メモリ割り当てとヒープ サイズを増やすこともできます。
org.gradle.jvmargs=-Xmx2048M -XX\:MaxHeapSize\=32g
2048M と 32g である必要はありません。好きなだけ大きくしてください。
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**
@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 言語仕様からのものです。