8

このメソッドを呼び出すと、java outOfMemoryErrorが発生します。これをループで使用して、多数の大きなファイルを順番に解析しています。私の推測ではresult.toString()、ループ中にガベージコレクションが適切に収集されていません。もしそうなら、どのように修正すればよいですか?

private String matchHelper(String buffer, String regex, String method){
    Pattern abbrev_p = Pattern.compile(regex);//norms U.S.A., B.S., PH.D, PH.D.
    Matcher abbrev_matcher = abbrev_p.matcher(buffer);
    StringBuffer result = new StringBuffer();
    while (abbrev_matcher.find()){
            abbrev_matcher.appendReplacement(result, abbrevHelper(abbrev_matcher));
    }
    abbrev_matcher.appendTail(result);
    String tempResult = result.toString(); //ERROR OCCURS HERE
  return tempResult;

}
4

6 に答える 6

8

このように書くと、ファイル内の文字ごとに約6バイトのメモリが必要になります。

各文字は2バイトです。生の入力と(バッファ内の)置換された出力があり、メモリが不足したときに3番目のコピーを要求しています。

ファイルがASCIIやISO-8859-1(1バイト文字エンコード)のようなものでエンコードされている場合、それはディスクよりもメモリ内で6倍大きくなることを意味します。

より多くのメモリをプロセスに割り当てることもできますが、より良い解決策は、入力を「ストリーム単位」で処理することです。つまり、データを一度にすべてメモリにロードせずに、データの読み取り、スキャン、および書き込みを行います。

于 2010-03-12T07:20:13.763 に答える
6

処理するファイルがすべて非常に大きい場合、たとえば数百 MB 以上の場合は、@erickson が提案したように、この「すべてをメモリにロードする」方法ではなく、ストリーム処理を使用する必要があります。

それ以外の場合は、可能な限りメモリ使用量を削減するために試すことができるいくつかのことがあります。

  1. まだヒープサイズを拡大していない場合は、適切に拡大してみてください (該当する場合)。
  2. 指定StringBufferされた の長さと同じ初期サイズを指定しString bufferます。これにより、プロセス内で を拡張しながら、不要なメモリ使用量を削減できStringBufferます。元の文字列の特定の単語を置き換えるだけで、長さはほぼ同じであると思います。
  3. 可能であれば、StringBuffer代わりに生成されたオブジェクトを返すことができます。元のオブジェクトtoString()を削除した後にのみ呼び出します。String
于 2010-03-12T07:26:56.773 に答える
2

に問題があると思いますStringBuilder.append()。Matcher が一連の文字を Builder に追加するとき。

OutOfMemoryError with StringBuilder/StringBufferに関する記事で説明されているcharsように、容量が十分でない場合、内部バッファーの場合に append() が容量を 2 倍にすることが既知の問題です。Erickson の提案に従って、ストリームにアクセスしてください。

于 2010-09-17T07:56:54.060 に答える
1

はい!メモリにバッファリングしないでください。そうしないと、I/O で 2MB を超える場合に特別に不足してしまいます。

テキストを修正して追加するための推奨リンク: http://java.ittoolbox.com/documents/appending-data-to-a-file-18786

于 2010-10-01T15:51:53.833 に答える
1

私は他の回答に同意します...しかし...例外が発生したからといって、必ずしもそれが問題であるとは限りません。他の場所でメモリをリークしている可能性が非常に高く、それが明らかになった場所です。プロファイラーを実行してメモリ使用量を調べ、どのオブジェクトが収集されていないかを正確に確認する必要があります。

于 2010-03-12T07:29:34.980 に答える
0

を返して、使用後StringBufferにに設定してみてくださいnull

于 2010-03-12T07:09:52.123 に答える