321

それぞれ数個 (15 ~ 20 個) のテキスト エントリを持つ数個 (数十万個) の HashMap オブジェクトを作成するプログラムで、このエラーが発生します。これらの文字列は、データベースに送信される前にすべて (少量に分割せずに) 収集する必要があります。

Sun によると、エラーは「ガベージ コレクションに費やされている時間が長すぎる場合に発生します。総時間の 98% 以上がガベージ コレクションに費やされ、回復されたヒープが 2% 未満の場合、OutOfMemoryError がスローされます。 "。

どうやら、コマンドラインを使用してJVMに引数を渡すことができます

  • 「-Xmx1024m」(またはそれ以上)を介してヒープサイズを増やす、または
  • 「-XX:-UseGCOverheadLimit」を使用して、エラー チェックを完全に無効にします。

最初のアプローチは問題なく機能しますが、2 番目のアプローチは別の java.lang.OutOfMemoryError で終わります。今回はヒープに関するものです。

では、質問: 特定のユースケース (つまり、いくつかの小さな HashMap オブジェクト) に対して、これに代わるプログラムはありますか? たとえば、HashMap の clear() メソッドを使用すると、問題は解消されますが、HashMap に格納されているデータも解消されます。:-)

この問題は、StackOverflow の関連トピックでも説明されています。

4

16 に答える 16

157

プロセスをスムーズに実行するには、基本的にメモリが不足しています。頭に浮かぶオプション:

  1. あなたが言及したようにより多くのメモリを指定し、-Xmx512m最初のような間に何かを試してください
  2. HashMap可能であれば、一度に処理するオブジェクトの小さなバッチで作業する
  3. 重複する文字列がたくさんある場合は、String.intern()それらをHashMap
  4. HashMap(int initialCapacity, float loadFactor)コンストラクターを使用してケースに合わせて調整する
于 2011-04-30T04:00:30.513 に答える
61

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

dexOptions {
        javaMaxHeapSize "4g"
}

あなたにbuild.gradle

android {
    compileSdkVersion 23
    buildToolsVersion '23.0.1'

    defaultConfig {
        applicationId "yourpackage"
        minSdkVersion 14
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"

        multiDexEnabled true
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    packagingOptions {

    }

    dexOptions {
        javaMaxHeapSize "4g"
    }
}
于 2015-11-22T11:47:01.697 に答える
43

@takrl: このオプションのデフォルト設定は次のとおりです。

java -XX:+UseConcMarkSweepGC

つまり、このオプションはデフォルトではアクティブではありません。したがって、オプション " " を使用したと言うときは、次の+XX:UseConcMarkSweepGC構文を使用していたと思います。

java -XX:+UseConcMarkSweepGC

これは、このオプションを明示的に有効にしたことを意味します。Java HotSpot VM Options@ の正しい構文とデフォルト設定については、このドキュメントを参照してください。

于 2012-02-03T09:16:10.450 に答える
24

ちなみに、今日も同じ問題がありました。このオプションを使用して修正しました。

-XX:-UseConcMarkSweepGC

どうやら、これはガベージコレクションに使用される戦略を変更し、問題を解消しました。

于 2011-10-12T14:38:50.043 に答える
11

うーん...次のいずれかが必要です。

  1. これらの小さな HashMap をすべて必要としないように、アルゴリズムとデータ構造を完全に再考してください。

  2. これらの HashMap を必要に応じてメモリの内外にページングできるようにするファサードを作成します。単純な LRU キャッシュは単なるチケットかもしれません。

  3. JVM で使用できるメモリを増やします。この獣をホストするマシンを管理している場合は、必要に応じて、さらに RAM を購入することが最も迅速で安価なソリューションになる可能性があります。そうは言っても、私は通常、「ハードウェアをさらに投入する」ソリューションのファンではありません。特に、代替のアルゴリズムソリューションが妥当な時間枠内で考えられる場合はなおさらです。これらの問題のすべてにさらに多くのハードウェアを投入し続けると、すぐに収穫逓減の法則に突き当たります。

とにかく、あなたは実際に何をしようとしていますか?あなたの実際の問題に対するより良いアプローチがあると思います。

于 2011-04-30T04:01:42.107 に答える
10

別の HashMap 実装 ( Trove ) を使用します。標準の Java HashMap には、12 倍を超えるメモリ オーバーヘッドがあります。ここで詳細を読むことができます。

于 2013-01-17T17:01:54.417 に答える
9

最後に到達するのを待っている間、構造全体をメモリに保存しないでください。

中間結果をハッシュマップの代わりにデータベースの一時テーブルに書き込みます。機能的には、データベース テーブルはハッシュマップと同等です。つまり、どちらもデータへのキー付きアクセスをサポートしますが、テーブルはメモリ バウンドではありません。ハッシュマップ。

正しく行われた場合、アルゴリズムは変更に気付かないはずです。ここでは、クラスを使用してテーブルを表すことを意味し、ハッシュマップのように put(key, value) および get(key) メソッドを与えます。

中間テーブルが完成したら、メモリからではなく中間テーブルから必要な sql ステートメントを生成します。

于 2013-01-28T19:07:28.780 に答える
3

Eclipse MATVisualVMなどのプロファイル ツールを使用して、アプリケーションのメモリ リークを修正します。

JDK 1.7.x以降のバージョンでは、他の GC アルゴリズムの 2% とは異なり、ガベージ コレクションに 10% を費やす を使用しG1GCます

でヒープメモリを設定する以外に-Xms1g -Xmx2g、 ` を試してください

-XX:+UseG1GC 
-XX:G1HeapRegionSize=n, 
-XX:MaxGCPauseMillis=m, 
-XX:ParallelGCThreads=n, 
-XX:ConcGCThreads=n`

これらのパラメータの微調整については、Oracle の記事を参照してください

SE の G1GC に関するいくつかの質問:

Java 7 (JDK 7) ガベージ コレクションと G1 に関するドキュメント

本番環境での Java G1 ガベージ コレクション

積極的なガベージ コレクター戦略

于 2015-12-15T18:22:46.437 に答える
3

これを行うには、Android クロージャーの下でアプリの gradle ファイルで以下のコードを使用します。

dexOptions { javaMaxHeapSize "4g" }

于 2017-02-24T09:41:00.237 に答える
2

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
)
and

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-14T10:41:58.943 に答える
2

In case of the error:

"Internal compiler error: java.lang.OutOfMemoryError: GC overhead limit exceeded at java.lang.AbstractStringBuilder"

increase the java heap space to 2GB i.e., -Xmx2g.

于 2013-01-23T07:56:34.107 に答える
0

これにより、このエラーを取り除くことができました。このオプションは -XX:+DisableExplicitGC を無効にします。

于 2012-12-07T16:13:07.313 に答える