Java写入ByteArrayOutputStream内存泄漏

时间:2012-08-15 14:04:27

标签: java sockets memory-leaks bytearrayoutputstream

我正在将图像字节写入ByteArrayOutputStream,然后通过套接字发送它。 问题是,当我这样做时

ImageIO.write(image, "gif", byteArray);

内存非常多,有点内存泄漏。

我使用此

发送
ImageIO.write(image, "gif", byteArrayO);         
byte [] byteArray = byteArrayO.toByteArray();
byteArrayO.flush();
byteArrayO.reset();
Connection.pw.println("" + byteArray.length);
int old = Connection.client.getSendBufferSize();
Connection.client.setSendBufferSize(byteArray.length);
Connection.client.getOutputStream().write(byteArray, 0, byteArray.length);
Connection.client.getOutputStream().flush();
image.flush();
image = null;
byteArrayO = null;
byteArray = null;
System.gc();
Connection.client.setSendBufferSize(old);

正如您所看到的,我已经尝试过所有方法,当我写入ByteArrayOutputStream时,错误就出现了,而不是在我转移它时。接收方没有任何错误。

任何方法我都可以清除byteArray,并从内存中删除它中的所有内容?我知道reset()有,但它不在这里。我想在完成后直接处理ByteArrayOutputStream

5 个答案:

答案 0 :(得分:4)

为什么你必须摆弄发送缓冲区大小?你在这个套接字上使用什么样的协议?它应该就像:

一样简单
ImageIO.write(image, "gif", Connection.client.getOutputStream());

如果必须使用ByteArrayOutputStream,请至少使用

byteArrayO.writeTo(Connection.client.getOutputStream())

所以你不要多余byte[]

答案 1 :(得分:4)

@ChristofferHammarström可能有最好的解决方案,但我会添加它来尝试解释内存使用情况。

这2行创建了3个图像数据副本:

ImageIO.write(image, "gif", byteArrayO);
byte [] byteArray = byteArrayO.toByteArray(); 

执行此操作后,您将拥有一个存储在image中的数据副本,一个副本位于ByteArrayOutputStream中,另一个副本位于字节数组中(toByteArray()不返回它创建副本的内部缓冲区。)

调用reset()不释放ByteArrayOutputStream中的内存,它只是将位置计数器重置为0.数据仍在那里。

要允许先前释放内存,您可以在完成后立即将每个项目指定为null。这将允许垃圾收集器收集内存,如果它决定先运行。 EG:

ImageIO.write(image, "gif", byteArrayO);
image = null;
byte [] byteArray = byteArrayO.toByteArray(); 
byteArrayO = null;
...

答案 2 :(得分:1)

这不是你想要的答案,而是你可能想要考虑的事情。

为什么不创建一个字节数组池,并在每次需要时重新使用它们。这样会更有效率,因为您不会一直创建新阵列并将它们丢弃。使用较少的gc总是一件好事。您还可以保证应用程序有足够的内存来运行。

答案 3 :(得分:0)

您可以请求VM通过System.gc()运行垃圾回收,但不保证实际发生。虚拟机在确定有必要或适当的时候执行垃圾收集。

答案 4 :(得分:0)

你所描述的是很正常的。它必须将您正在创建的图像的字节放在某处。

您可以使用FileOutputStream将字节写入,而不是内存。然后,您必须创建一个FileInputStream来从您写入的文件中读取一个循环,该循环将字节读入一个64k大小的字节数组缓冲区,然后将这些字节写入连接的输出流。

你提到错误。如果您收到错误,那么错误是什么?

如果使用客户端JVM(java的-client参数),则可能会将内存返回给操作系统,Java进程将再次收缩。我不确定这一点。

如果您不喜欢JAI使用多少内存,可以尝试使用Sanselan:http://commons.apache.org/imaging/