7

2.5 GB の txt ファイルをアプリケーションに読み込もうとしています。私は Win7 x64 を実行しており、43GB のメモリを使用できます (64GB のうち)。-Xmx -XX:MaxParmSize -XX:ParmSize などで遊んでみました。これらのどれもエラーに影響しません。他に何を試すことができますか?確かに十分なヒープ領域が利用可能であるため、このエラーは非常に奇妙に思えます。

Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit
    at java.util.Arrays.copyOf(Unknown Source)
    at java.lang.AbstractStringBuilder.expandCapacity(Unknown Source)
    at java.lang.AbstractStringBuilder.ensureCapacityInternal(Unknown Source)
    at java.lang.AbstractStringBuilder.append(Unknown Source)
    at java.lang.StringBuilder.append(Unknown Source)
    at j.utilities.IO.loadString(IO.java:187)
    at j.utilities.IO.loadString(IO.java:169)
    at city.PreProcess.main(PreProcess.java:78)

私は走っています

java version "1.7.0_09"
Java(TM) SE Runtime Environment (build 1.7.0_09-b05)
Java HotSpot(TM) 64-Bit Server VM (build 23.5-b02, mixed mode)

よろしくお願いします。

============== 答え ==============

OK、私はそれをテストしました

StringBuilder sb = new StringBuilder();
for ( int i=1; i<Integer.MAX_VALUE; i++ )
    sb.append("x");

そして得た

Exception in thread "main" java.lang.OutOfMemoryError: Requested array size exceeds VM limit
at java.util.Arrays.copyOf(Unknown Source)
...

したがって、Integer.MAX_VALUE よりも大きな配列を構築しようとするのは、実際には StringBuilder です。

興味がある場合

StringBuilder sb = new StringBuilder();
int i=1;
try {
    for ( ; i<Integer.MAX_VALUE; i++ )
        sb.append("x");
} catch ( OutOfMemoryError e ) {
    System.out.println(i); // OUTPUT: 1207959551
    System.out.println(Integer.MAX_VALUE); // OUTPUT: 2147483647
}

StringBuilder を使用すると、1,207,959,550 文字を蓄積できます。これは、Integer.MAX_VALUE よりもはるかに少ない値です。

4

4 に答える 4

10

大きすぎる配列を割り当てようとしています。これは、非常に長い文字列を作成しようとしているためです。配列は整数でインデックス付けされるため、配列は 個以上のInteger.MAX_VALUE要素を持つことはできません。ヒープ サイズが非常に大きい場合でもInteger.MAX_VALUEInteger. Java 配列には最大サイズがありますか? を参照してください。詳細については。

于 2012-12-07T23:50:22.273 に答える
3

たとえば、サイズを指定して新しい StringBuilder を作成できます。

    StringBuilder sb = new StringBuilder(Integer.MAX_VALUE);

問題は、 StringBuilder がその配列に持つことができるものよりも大きいファイルを読み込もうとしていることです。いくつかのオプションがあります。

1) ファイル全体を一度にメモリに読み込む必要がありますか? その場合、いくつかの StringBuilders に読み込む必要があります。

2) ファイルを順次処理します。

3) 圧縮構造に読み込み、必要なときに必要な部分を解凍します。

于 2012-12-08T00:42:19.160 に答える
0

文字列バッファにデータを保持しList<String>、定義区間内のデータをクリアすることができますStringBuffer

于 2014-03-31T22:11:01.553 に答える
0

java コマンドの -Xmsn オプションを調べる必要があります。

メモリ割り当てプールの初期サイズを指定します。

編集:あなたはすでにそれを行っているようです。

于 2012-12-07T23:53:05.007 に答える