2012-04-24 4 views
5

tengo el siguiente código que produce una excepción OutOfMemory:No se puede escribir en DataOutputStream más allá de un tamaño específico - OutOfMemoryError

byte[] buf = new byte[10240]; 
int len = 0; 
DataOutputStream dataOS = new DataOutputStream(conn.getOutputStream()); 
while ((len = _inputStream.read(buf)) > 0) { 
    System.out.println("len : " + len); 
    System.out.println("Going to write buf into dataOS : " + buf.length); 
    dataOS.write(buf, 0, len); 
    System.out.println("dataOS.size() : " + dataOS.size()); 
} 
_inputStream.close(); 

El siguiente es las últimas líneas de la salida de depuración:

len : 10240 
Going to write buf into dataOS : 10240 
dataOS.size() : 342804702 
len : 10240 
Going to write buf into dataOS : 10240 
dataOS.size() : 342814942 
len : 10240 
Going to write buf into dataOS : 10240 

La excepción se produce cuando intento escribir en el dataOS más allá de 342814942.

¿Podría alguien ayudarme a manejar esto?

Gracias!

+1

Como Sharakan dice, se debe vaciar el búfer con regularidad, pero si realmente no desea eliminar, aumentar la asignación de memoria para la JVM (parámetro -Xmx sobre el inicio de Java). – Renato

Respuesta

14

No tiene nada que ver con el DataOutputStream (que no mantiene ningún tipo de datos) y todo lo relacionado con su secuencia subyacente conn.getOutputStream(). ahora, no ha mostrado el código relevante allí, pero supongo que "conn" es una instancia de HttpURLConnection. Creo que el outputtream para HttpURLConnection almacena temporalmente el resultado para que pueda determinar la duración de la salida (a menos que lo configure explícitamente). si se conoce la longitud de salida, se puede establecer que el uso de HttpURLConnection.setFixedLengthStreamingMode directamente, o se le puede llamar HttpURLConnection.setChunkedStreamMode para permitir que los datos sean enviados en trozos en lugar de amortiguadas por completo en la memoria.

En el futuro, cuando encuentre un OOME, debe siempre generar un volcado de pila y abrirlo en un generador de perfiles de memoria. que casi siempre le mostrará inmediatamente dónde está el problema (por ejemplo, en la secuencia subyacente, no la DataOutputStream).

+0

jtahlborn: Muchas gracias. El problema era realmente hacer con conn.getOutputStream(). Y sí, es una HttpURLConnection. Disculpas por no ser específico. Intenté establecer setFixedLengthStreamingMode en la longitud del archivo y parece ir más allá del tamaño anterior. Gracias. Estoy usando dataOS para subir datos a un servidor. Por lo tanto, cuando uso setChunkedStreamMode, ¿debo manejar la carga de una manera diferente? Ahora mismo llamo a conn.getResponseCode() para cargar. Por favor recomiende. – Ram

+2

@Ram - por un lado, que no tienen necesidad de la DataOutputStream (sólo tiene que utilizar el flujo de salida conn directamente). si usa la transmisión en bloque, _you_ no necesita hacer nada diferente en su extremo. el servidor en el otro extremo necesita soportar codificación fragmentada (pero la mayoría lo hace). – jtahlborn

+0

Muchas gracias. Voy a probar eso. – Ram

1

Dependiendo de la implementación de OutputStream, la escritura puede amortiguar el contenido en la memoria, y en realidad no enviarlo. Si almacena suficiente contenido, se quedará sin memoria.

En algún intervalo, tal vez cada vez que a través de su bucle, debe llamar OutputStream.flush(). Si hay un buffer en uso, eso lo borrará.

+2

prácticamente todas las implementaciones de flujo que almacenan los datos vacíos _configuran automáticamente los datos cuando el búfer interno está lleno. – jtahlborn

+0

@jtahlborn Eso no me sorprendería, pero hasta donde sé, eso no forma parte del contrato. Tal vez puedas dar un ejemplo? – sharakan

+0

cada implementación de flujo en java, excepto tal vez la secuencia de salida http cuando intenta determinar la longitud de salida. – jtahlborn

Cuestiones relacionadas