Domanda

sto diventando un OutOfMemoryError java quando chiamo questo metodo - lo sto usando in un ciclo per analizzare molti file di grandi dimensioni in sequenza. La mia ipotesi è che non è sempre result.toString() garbage collection correttamente durante il ciclo. in caso affermativo, come devo risolvere il problema?

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;

}
È stato utile?

Soluzione

Scritto in questo modo, avrete bisogno di circa 6 byte di memoria per ogni personaggio nel file.

Ogni carattere è di due byte. Avete l'ingresso grezzo, l'uscita sostituito (nel buffer), e si sta chiedendo una terza copia quando si esaurisce la memoria.

Se il file viene codificato in qualcosa come ASCII o ISO-8859-1 (una codifica dei caratteri a singolo byte), che significa che sarà sei volte più grande in memoria che su disco.

Si può allocare più memoria al processo, ma una soluzione migliore potrebbe essere per elaborare l'ingresso -Read "streamwise", scansione, e scrivere i dati senza caricare tutto in memoria in una volta.

Altri suggerimenti

Se i file da elaborare sono tutte molto grandi, dicono più di qualche centinaio di MB, allora davvero dovrebbe andare con l'elaborazione di flusso, invece di questo modo "carico tutto in memoria", proprio come suggerito @erickson.

In caso contrario, ci sono alcune cose che si potrebbe provare, tutto per ridurre l'utilizzo della memoria il più possibile:

  1. Prova ingrandire correttamente la dimensione heap se non ancora (se applicabile).
  2. Dare StringBuffer una dimensione iniziale uguale alla lunghezza della data String buffer. Questo dovrebbe ridurre l'utilizzo della memoria non necessaria, mentre l'espansione del StringBuffer nel processo. Suppongo che sostituisce solo alcune parole della stringa originale e dovrebbe essere più o meno la stessa lunghezza.
  3. Se possibile, forse si potrebbe restituire l'oggetto StringBuffer generato invece. Chiamando il suo toString() solo dopo aver sbarazzarsi dell'oggetto String originale.

Mi sa che il problema con StringBuilder.append(). Quando Matcher aggiunge sequenza di caratteri al costruttore.

Come spiegato in un articolo sulla OutOfMemoryError con StringBuilder / StringBuffer , è un problema noto che append () raddoppierà la capacità se chars buffer interno se la capacità non è sufficiente. Andare per i flussi come suggerito da Erickson.

Sono d'accordo con le altre risposte ... ma ... semplicemente perché si verifica l'eccezione, non ci fa necessariamente significa che sia il problema. Si può benissimo essere perdite di memoria altrove e che solo sembra essere il luogo che viene rivelato. Si consiglia di eseguire un profiler per esaminare l'utilizzo di memoria e verificare esattamente ciò che gli oggetti non vengono raccolti.

Sì! Non buffer nella memoria altrimenti si esegue fuori di esso specialmente se si sta andando oltre 2MB su I / O.

collegamento consigliato per il fissaggio e aggiungendo il testo: http: // java.ittoolbox.com/documents/appending-data-to-a-file-18786

Si potrebbe provare la restituzione di un StringBuffer e impostarla a null dopo l'uso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top