2011-05-20 14 views
7

No soy experto en Java.Java String Memory Leak

Mi código está leyendo un archivo en un String. Este código se ejecuta cada 5 minutos. El tamaño del archivo varía. A veces es 100 a veces es 1000 líneas.

Tengo experiencia fuera de la memoria, después de algunos días.

La pregunta que tengo es, cuando mis códigos quedan fuera del alcance de Reading file function, ¿la basura de Java recoge la cadena?

Estoy bastante confundido leyendo en Internet. Algunas personas dicen que no se borra y usan StringBuffer.

// Demonstrate FileReader. 

import java.io.*; 
class FileReaderDemo { 
    public static void read(BufferedReader br) throws Exception { 
     long length = 0; 
     String s; 
     while (true) { 
      s = br.readLine(); 
      s += "abcd"; 
      if (s == null) { 
       break; 
      } 
      length += s.length(); 
      //System.out.println(s); 
     } 
     System.out.println("Read: " + (length/1024/1024) + " MB"); 
    } 

    public static void main(String args[]) throws Exception { 
     //FileReader fr = new FileReader("FileReaderDemo.java"); 
     FileReader fr = new FileReader("big_file.txt.1"); 
     BufferedReader br = new BufferedReader(fr); 
     String s; 
     read(br); 
     fr = new FileReader("big_file.txt.1"); 
     br = new BufferedReader(fr); 
     read(br); 
     fr = new FileReader("big_file.txt.1"); 
     br = new BufferedReader(fr); 
     read(br); 
     fr = new FileReader("big_file.txt.1"); 
     br = new BufferedReader(fr); 
     read(br); 
     BufferedReader in = new BufferedReader(new InputStreamReader(System. in)); in .readLine(); 
     fr.close(); 
    } 
} 
+4

Depende. Las cadenas son objetos. Con los objetos, depende de si el objeto recibe alguna referencia (por ejemplo, el valor de retorno del método). ¿Puedes publicar algún código? –

+2

Sería bueno, de hecho, ver el código y lo que está haciendo con las cadenas que lee. Trate de darnos un poco [SSCCE] (http://sscce.org/) – Boro

+1

No veo cómo el código publicaste podías correr por días. – Anonymoose

Respuesta

3

El código que has publicado no perder memoria. Sin embargo, el bucle while (true) nunca terminará porque s nunca será null en el punto en que lo prueba.


permite cambiar un poco para que sea "trabajar"

public static void read(BufferedReader br) throws Exception { 
      long length = 0; 
      String s = ""; 
      while (true) { 
        String ss = br.readLine(); 
        if (ss == null) { 
          break; 
        } 
        s += ss; 
        length += ss.length(); 
      } 
      System.out.println("Read: " + (length/1024/1024) + " MB"); 
    } 

Este código no tiene fugas de memoria, ya sea porque las cadenas creadas en el método serán todos los candidatos a la recolección de basura cuando el método vuelve (si no antes).

Cada vez que ejecutamos s += ss;, se crea una nueva cadena que consta de todos los caracteres actualmente en s y los caracteres en ss. Suponiendo que hay N líneas que contienen un promedio de L caracteres, la instrucción s += ss; se llamará N veces, creará N cadenas y copiará en promedio (N * L)^2/2 caracteres.


Sin embargo, no es una buena razón para hacer una StringBuilder y que consiste en reducir la cantidad de asignación de cuerdas y la copia carácter que sigue. Permite reescribir el método para usar un StringBuilder; es decir, un reemplazo para StringBuffer que no está sincronizado.

public static void read(BufferedReader br) throws Exception { 
      long length = 0; 
      StringBuilder sb = new StringBuilder(sb); 
      while (true) { 
        String ss = br.readLine(); 
        if (ss == null) { 
          break; 
        } 
        sb.append(ss); 
        length += ss.length(); 
      } 
      System.out.println("Read: " + (length/1024/1024) + " MB"); 
    } 

Esta versión reasignará matriz de caracteres interno de la StringBuilder en la mayoría delog2(N) veces y copiar en la mayoría de 2 * N * L caracteres.


Resumen: utilizar StringBuilder es una buena idea, pero no debido a fugas de memoria. Si tiene una pérdida de memoria, no está en el código de muestra original o en la versión fija.

6

Hola, no soy experto en java.

Todo el mundo tiene algo que pueden aprender.

Mi código está leyendo un archivo en una cadena, este código se ejecuta cada 5 minutos. Ahora Algún tamaño de archivo de 100 líneas a veces 1000 líneas.

No suena muy grande o muy a menudo. No debería ser un problema.

Tengo la experiencia Fuera de la memoria, después de algunos días.

Debería poder obtener un volcado de pila y ver dónde se ha quedado sin memoria y por qué.

Pregunta que tengo es, Cuando mis códigos quedan fuera del alcance de la función de Lectura de archivos. ¿Java Garbage recolecta la cadena?

Se puede recoger cuando ya no se puede acceder a través de una referencia fuerte.

estoy bastante confundir por la lectura en Internet algunos dice que no se borran y el uso de StringBuffer

suena como usted llegó al lugar correcto. Nunca he escuchado eso.

5

Su método read nunca terminará. Una vez que llegue al final del archivo, simplemente continúe agregando la cadena "nullabcd" al s, para siempre.

EDITAR: olvida que, s se vuelve a asignar cada vez. Aún así, no puedo ver cómo puede finalizar su método read.

+0

Sí, tengo la fuerte sensación de que el código que se publicó no es el real código que está teniendo problemas. – Anonymoose

2

cambie el programa siguiente para consumir menos memoria. Una gran fuente de consumo de memoria se debe a su repetida concatenación de cadenas de s += "abcd";; evite eso y probablemente reducirá a la mitad el consumo de memoria (no probado), hágalo usted mismo si quiere saberlo.

public static void read(BufferedReader br) throws Exception { 

    long length = 0; 
    //String s; <--- change to the line below 
    StringBuilder sb = new StringBuilder(); 
    while (true) { 
     String s = br.readLine(); 
     if (s == null) { 
      break; 
     } 
     //s += "abcd"; <--- change to the line below 
     sb.append(s).append("abcd"); 
     length += s.length(); 
     //System.out.println(s); 
    } 
    System.out.println("Read: " + (length/1024/1024) + " MB"); 
} 
1

Como han señalado otros, este código nunca termina. Parece que el código que publicaste no es el código original con el que tienes problemas.

Difícil de diagnosticar sin ver el código real, pero Strings será definitivamente será basura recolectada una vez que no se haga referencia a ellas desde otras partes del código.

Wild guess: ¿Está llamando close() en sus lectores y InputStreams una vez que haya terminado con ellos? De lo contrario, esta podría ser la causa de los errores de falta de memoria.