我有以下代码产生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
当我尝试写入342814942以外的dataOS时会发生异常。
有人可以帮我解决这个问题吗?
谢谢!
答案 0 :(得分:14)
它与DataOutputStream(它不保留任何数据)以及与基础流conn.getOutputStream()
有关的一切无关。现在,你没有在那里显示相关代码,但我猜测“conn”是HttpURLConnection的一个实例。我相信HttpURLConnection的输出流缓冲输出,以便它可以确定输出长度(除非你明确设置它)。如果您知道输出长度,可以直接使用HttpURLConnection.setFixedLengthStreamingMode
设置,或者可以调用HttpURLConnection.setChunkedStreamMode
以允许数据以块的形式发送,而不是完全缓存在内存中。
将来,当遇到OOME时,您应该始终生成堆转储并在内存分析器中打开它。几乎总会立即向您显示问题所在(例如在基础流中,不 DataOutputStream)。
答案 1 :(得分:1)
根据OutputStream的实现,写入可能会缓冲内存中的内容,而不是实际发送它。如果你缓冲了足够的内容,你当然会耗尽内存。
在某个时间间隔,也许每次通过你的循环,你应该拨打OutputStream.flush()
。如果正在使用缓冲区,则会清除它。