2010-03-12 15 views
6

Ich erhalte einen Java OutOfMemoryError, wenn ich diese Methode aufrufen - ich verwende es in einer Schleife, um viele große Dateien nacheinander zu analysieren. Meine Vermutung ist, dass result.toString() nicht richtig Müll während der Schleife gesammelt wird. Wenn ja, wie sollte ich es beheben?java outOfMemoryError mit stringbuilder

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; 

} 
+2

Wie groß ist eine "große Datei"? Es kann sein, dass Sie der JVM nicht genügend Speicher zuweisen. – Ash

+0

Fehlertext für weitere Untersuchungen anzeigen. – Artic

+0

Wie wäre es mit dem reinen String von OString Länge: 2769348? Die meisten der String ist der NexString der Fotos erfasst –

Antwort

6

Auf diese Weise geschrieben, benötigen Sie etwa Byte Speicher für jedes Zeichen in der Datei.

Jedes Zeichen besteht aus zwei Bytes. Sie haben die rohe Eingabe, die ersetzte Ausgabe (im Puffer) und Sie fragen nach einer dritten Kopie, wenn Sie nicht mehr genügend Arbeitsspeicher haben.

Wenn die Datei in etwas wie ASCII oder ISO-8859-1 codiert ist (eine Einzelbyte-Zeichencodierung), bedeutet dies, dass sie im Speicher sechs Mal größer ist als auf der Festplatte.

Sie könnten dem Prozess mehr Speicher zuweisen, aber eine bessere Lösung könnte sein, die Eingabe "streamwise" — zu lesen, zu scannen und die Daten zu schreiben, ohne sie alle gleichzeitig in den Speicher zu laden.

+1

Daumen hoch. Wenn Ihre Verarbeitung auf einer Zeile-für-Zeile-Arbeit basiert, können Sie einfach Folgendes verwenden: 'BufferedReader rd = new BufferedReader (neuer FileReader ("/Pfad/zu/Ihrer/Datei "));' und read 'readLine () 'in einer 'while'-Schleife, dann das Ersetzen und tun, was auch immer mit der geänderten Zeile notwendig ist. – dimitarvp

0

könnten Sie versuchen, eine StringBuffer Rückkehr und es null nach Gebrauch einstellen.

2

Wenn Ihre zu verarbeitenden Dateien sind alle sehr groß, sagen mehr als ein paar hundert MB, dann sollten Sie wirklich mit Stream-Verarbeitung gehen statt dieser "alle in den Speicher" Weg, wie @erickson vorgeschlagen.

Ansonsten gibt es ein paar Dinge, die Sie könnten versuchen, alle Speicherverbrauch so weit wie möglich zu reduzieren:

  1. richtig die Heap-Größe vergrößern versuchen, wenn noch nicht (wenn zutreffend).
  2. Geben Sie StringBuffer eine Anfangsgröße, die der Länge des angegebenen Stringbuffer entspricht. Dies sollte die unnötige Speicherauslastung verringern und gleichzeitig die StringBuffer erweitern. Ich nehme an, es ersetzt nur bestimmte Wörter der ursprünglichen Zeichenfolge und sollte mehr oder weniger die gleiche Länge haben.
  3. Wenn möglich, könnten Sie möglicherweise das generierte Objekt StringBuffer zurückgeben. Rufen Sie toString() nur auf, nachdem Sie das ursprüngliche Objekt String losgeworden sind.
+0

Vergrößern Heap Größe woks. –

1

Ich stimme mit den anderen Antworten ... aber ... einfach, weil die Ausnahme tritt nicht notwendigerweise bedeutet es das Problem. Sie können sehr gut leaking memory woanders sein und das ist zufällig der Ort, der aufgedeckt wird. Sie sollten profiler ausführen, um die Speichernutzung zu überprüfen und genau zu überprüfen, welche Objekte nicht erfasst werden.

1

Ich rechne das Problem mit StringBuilder.append(). Wenn Matcher eine Zeichenfolge an den Builder anfügt.

Wie in Artikel über OutOfMemoryError with StringBuilder/StringBuffer erklärt, ist es ein bekanntes Problem, dass append() die Kapazität verdoppelt, wenn der interne Puffer chars, wenn die Kapazität nicht ausreicht. Gehen Sie für Streams wie von Erickson vorgeschlagen.

Verwandte Themen