2010-03-12 24 views
6

Estoy obteniendo un java outOfMemoryError cuando llamo a este método - lo estoy usando en un bucle para analizar muchos archivos grandes en secuencia. mi suposición es que result.toString() no está recibiendo basura recogida correctamente durante el ciclo. si es así, ¿cómo debería solucionarlo?java outOfMemoryError con 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

¿Qué tan grande es un "gran archivo"? Puede ser que no esté asignando suficiente memoria a la JVM. – Ash

+0

Mostrar texto de error para futuras investigaciones. – Artic

+0

¿qué tal el puro String of OString Length: 2769348? La mayor parte de la cadena es el nexString de las fotos capturadas –

Respuesta

6

Escrito de esta manera, necesitará aproximadamente bytes de memoria para cada carácter en el archivo.

Cada carácter tiene dos bytes. Tiene la entrada sin procesar, la salida sustituida (en el búfer) y está solicitando una tercera copia cuando se queda sin memoria.

Si el archivo está codificado en algo como ASCII o ISO-8859-1 (una codificación de caracteres de un solo byte), eso significa que será seis veces más grande en memoria que en el disco.

Podría asignar más memoria al proceso, pero una mejor solución podría ser procesar la entrada "streamwise" — leer, escanear y escribir los datos sin cargar todo en la memoria a la vez.

+1

Thumbs up. Si su procesamiento se basa en el trabajo línea por línea, puede usar esto: 'BufferedReader rd = new BufferedReader (new FileReader ("/path/to/your/file "));' e invocar 'readLine () 'en un ciclo' while', luego haga las sustituciones y haga lo que sea necesario con la línea modificada. – dimitarvp

0

Usted podría intentar devolver un StringBuffer y se establece a null después de su uso.

2

Si los archivos que se procesarán son muy grandes, digamos más de unos cientos de MB, entonces debería ir con el procesamiento de flujo en lugar de este modo de "cargar todo en la memoria", como sugirió @erickson.

De lo contrario, hay algunas cosas que usted podría intentar, todo para reducir el uso de memoria tanto como sea posible:

  1. Trate agrandar correctamente el tamaño de la pila, si aún no (en su caso).
  2. Proporcione StringBuffer un tamaño inicial igual a la longitud del Stringbuffer dado. Esto debería reducir el uso innecesario de memoria al expandir el StringBuffer en el proceso. Supongo que solo está reemplazando ciertas palabras de la cadena original y debería ser más o menos la misma en longitud.
  3. Si es posible, tal vez podría devolver el objeto generado StringBuffer en su lugar. Llamando a su toString() solo después de deshacerse del objeto original String.
+0

ampliación de woks de tamaño de pila. –

1

Estoy de acuerdo con las otras respuestas, pero ... ... simplemente porque se produce la excepción no no significa necesariamente quiere decir que sea el problema. Puede ser leaking memory en otro lugar y ese es el lugar donde se revela. Debe ejecutar un profiler para examinar el uso de la memoria y verificar exactamente qué objetos no se están recopilando.

1

Creo que el problema es StringBuilder.append(). Cuando Matcher agrega una secuencia de caracteres al Constructor.

Como se explica en el artículo sobre OutOfMemoryError with StringBuilder/StringBuffer, es un problema conocido que append() se duplicará la capacidad si buffer interno chars si la capacidad no es suficiente. Ir a las secuencias como lo sugiere Erickson.