-2

我正在使用这样的 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。我尝试设置接收缓冲区大小,但它仍然保持不变。它在堆中达到最大值,然后停留一段时间然后停止。

如何清除缓冲区,以便在收到字节后将其处理掉?

4

5 回答 5

1

有几件事浮现在脑海:

  • 您可能会保留对对象的引用,而垃圾收集不会清理它。如果正在做这项工作的类是单例,这是一个很常见的问题。
  • 确保在您使用的任何 IO 类(如 BufferedInputSteam)上调用 close()。
于 2012-08-14T16:15:37.340 回答
0

我发表了评论,但也将其作为答案。

当您创建 in-memory时BufferedImage,您必须在完成后调用flush()它们。我非常怀疑您的内存泄漏来自于此。

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

System.gc()如果不是你的物理内存真的比你的memory-leak-free程序小,这不是一个解决方案,所以你必须在自己工作之前尝试它gc

于 2012-08-15T07:07:07.320 回答
0

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

于 2012-08-14T18:21:18.387 回答
0

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

尝试这个:

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

此外,您可以通过调用和让​​出线程来“推动”JVM 进行垃圾收集(您不能将其设为垃圾收集)。System.gc()如果单独归零不起作用,请尝试添加此

System.gc(); // "suggest" garbage collection to execute
Thread.yield(); // I have seen this encourage garbage collection to execute
于 2012-08-14T17:40:27.160 回答
0

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

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

我希望这有帮助!

于 2012-08-14T16:50:50.687 回答