Невозможно записать в DataOutputStream сверх определенного размера - OutOfMemoryError

У меня есть следующий код, который создает исключение OutOfMemory:

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();

Ниже приведены последние несколько строк отладочного вывода:

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

Исключение возникает, когда я пытаюсь записать в dataOS за 342814942.

Может ли кто-нибудь помочь мне справиться с этим?

Спасибо!

2 ответа

Решение

Он не имеет ничего общего с DataOutputStream (который не поддерживает никаких данных) и со всем, что связано с вашим основным потоком conn.getOutputStream(), сейчас вы не указали соответствующий код, но я собираюсь предположить, что "conn" является экземпляром HttpURLConnection. Я полагаю, что outputtream для HttpURLConnection буферизует вывод, чтобы он мог определить длину вывода (если вы не установили это явно). если вы знаете длину вывода, вы можете установить это непосредственно с помощью HttpURLConnection.setFixedLengthStreamingModeили вы можете позвонить HttpURLConnection.setChunkedStreamMode разрешить отправку данных в виде фрагментов, а не буферизовать их целиком в памяти.

в будущем, когда вы столкнетесь с OOME, вы всегда должны генерировать дамп кучи и открывать его в профилировщике памяти. это почти всегда сразу покажет вам, где проблема (например, в основном потоке, а не в DataOutputStream).

В зависимости от реализации OutputStream запись может буферизовать содержимое в памяти, а не отправлять его. Если вы буферизуете достаточно содержимого, вам, конечно, не хватит памяти.

Через определенный промежуток времени, возможно, каждый раз, когда вы проходите цикл OutputStream.flush(), Если используется буфер, это очистит его.

Другие вопросы по тегам