Java套接字,所有写入的内容都保留在内存中
我使用ByteArrayOutputStreams通过套接字发送图像,如下所示Java套接字,所有写入的内容都保留在内存中,java,sockets,inputstream,outputstream,Java,Sockets,Inputstream,Outputstream,我使用ByteArrayOutputStreams通过套接字发送图像,如下所示 ImageIO.write(image, "gif", byteArrayO); byte [] byteArray = byteArrayO.toByteArray(); Connection.pw.println("" + byteArray.length); int old = Connection.client.getSendBufferSize();
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);
int nbrToRead=Integer.parseInt(slave.input.readLine().trim());
int old=slave.socket.getReceiveBufferSize();
slave.socket.setReceiveBufferSize(NBRTREAD);
字节[]字节数组=新字节[NBRTREAD];
int nbrRd=0;
int nbrleefttoread=nbrread;
而(NbLeftToRead>0){
int rd=slave.socket.getInputStream().read(byteArray、nbrRd、nbrleftRead);
if(rd<0)
打破
nbrRd+=rd;
NbleFTREAD-=rd;
}
ByteArrayInputStream byteArrayI=新的ByteArrayInputStream(byteArray);
BuffereImage img=图像IO.read(byteArrayI);
它工作得很好,但是java内存堆中发送的每个映像都会增加50MB。我已尝试设置receivebuffersize,但它仍然保持不变。它在堆中达到最大值,然后停留一段时间,然后停止
如何清除缓冲区,以便在收到字节后处理它们?我想到了几件事:
- 您可能持有对某个对象的引用,而该对象并没有被垃圾收集清除。如果做这项工作的类是一个单例,这是一个非常常见的问题
- 确保对正在使用的任何IO类(如BufferedInputSteam)调用close()
null
来实现这一点
此外,完成后调用flush()
和close()
可以极大地提高内存使用率
我希望这有帮助 您还没有向我们展示您的所有方法,但是在等待下一个映像时,您可能在作用域中有大量内存局部变量 试试这个:
// 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
我敢打赌,
连接
持有一个对象输出流
。如果这是真的,那么您需要在该流上调用reset()
。我发表了评论,但也将其作为一个答案
当您在内存中创建buffereImage
s时,必须在处理完它们后调用flush()
。
我很怀疑你的记忆泄露就是由此而来的
而且,正如马拉奇所说,确保所有东西(缓冲区映像、I/O引用等)都没有任何类型的引用留给gc
对它们有效
System.gc(),客户端或服务器?连接是保存客户端和套接字的类。当您创建buffereImage
s时,您也必须对它们调用flush()
s。可能重复的flush()
s比close()
s更重要。ByteArrayInputStream没有flush()方法。ETA:但是flush()可能对发件人有用。。。没有足够的关于代码片段的信息可以看到。我很抱歉!我现在正在测试关闭它,我以为它会关闭连接,但它只是关闭bytearrayoutputstream的本地实例。它在发送图像的一侧泄漏。不是接收器。现在我知道问题出在哪里了。几乎完全正确。我不确定我是否应该提出一个新问题,所以:当我创建bytearrayoutputstream的新实例并使用ImageIO.write将图像写入其中时,它首先在内存中增加100 mb,然后缓慢增加,几次之后它就停止工作了。是的,我冲洗、重置然后关闭它。是的。必须在发送端关闭()
,否则无法完成发送。请注意,close()
也会自动执行flush()
,因此无需同时调用flush()
。不。我将所有内容写入这个bytestream,然后将其“正常”写入套接字。这不是问题。很好。但当我对它进行映像IO时,内存会增加。当我停止使用流或关闭流时,它不会消失。不,我使用socket.getOutputStream()和socket.getInputStream()