Java套接字,写入的所有东西都留在内存中

时间:2012-08-14 16:06:09

标签: java sockets inputstream outputstream

我正在使用像这样的ByteArrayOutputStreams通过套接字发送图像。

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

一切正常,图像最终是130kb,我就像这样接收

int nbrToRead = Integer.parseInt(slave.input.readLine().trim());
            int old = slave.socket.getReceiveBufferSize();
            slave.socket.setReceiveBufferSize(nbrToRead);
            byte[] byteArray = new byte[nbrToRead];
            int nbrRd = 0;
            int nbrLeftToRead = nbrToRead;
            while (nbrLeftToRead > 0) {
                int rd = slave.socket.getInputStream().read(byteArray, nbrRd, nbrLeftToRead);
                if (rd < 0)
                    break;
                nbrRd += rd; 
                nbrLeftToRead -= rd;
            }

            ByteArrayInputStream byteArrayI = new ByteArrayInputStream(byteArray);

            BufferedImage img = ImageIO.read(byteArrayI);

它运行良好,但每个发送java内存堆的图像增加了50 MB。我已经尝试过设置receivebuffersize,但它仍然保持不变。它在堆中达到最大值,然后停留一段时间然后停止。

如何清除缓冲区,以便在收到字节时它会处理它们?

5 个答案:

答案 0 :(得分:1)

有些事情让人想起:

  • 您可能正在坚持对对象的引用,并且它不会被垃圾回收清理。如果正在进行工作的班级是单身人士,这是一个非常普遍的问题。
  • 确保在您正在使用的任何IO类上调用close()(如BufferedInputSteam)。

答案 1 :(得分:0)

确保您的对象在发送后被取消引用,因为剩余的引用会将您的图像保留在内存中。您可以通过将该对象的所有实例设置为null来完成此操作。

此外,完成后调用flush()close()可以极大地帮助您的内存使用。

我希望这有帮助!

答案 2 :(得分:0)

您没有向我们展示您的所有方法,但在等待下一张图像时,您可能在范围内有大内存局部变量。

试试这个:

// after you've finished with the input, dereference the memory-heavy objects...
byteArray = null;
byteArrayI = null;

此外,您可以通过调用System.gc()并生成线程,将JVM“轻推”到垃圾收集(您无法使垃圾收集)。如果单独归零不起作用,请尝试添加此

System.gc(); // "suggest" garbage collection to execute
Thread.yield(); // I have seen this encourage garbage collection to execute

答案 3 :(得分:0)

我愿意打赌Connection拥有ObjectOutputStream。如果这是真的,那么您需要在该流上调用reset()

答案 4 :(得分:0)

我评论过,但也把它作为答案。

当您创建内存中BufferedImage时,必须在完成内容后调用flush()。 我非常怀疑你的内存泄漏是从那里来的。

而且,正如Malached所说,确保所有内容(BufferedImages,I / O引用等)都不会留下gc为他们工作的任何类型的引用。

System.gc()不是解决方案,如果情况不是您的物理内存确实小于memory-leak-free程序,那么您必须在gc自己工作之前尝试。< / p>