问题
I am sending images through sockets using ByteArrayOutputStreams like this.
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);
Everything works OK, the image is like 130kb in the end, and I receive it like this
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);
It works well, but every image sent the memory heap of java increases like 50 mb. I have tried setting the receivebuffersize, but it still stays up. It goes to maximum in heap, then stays for a while then stops.
How can I clear the buffer so when it has received the bytes it will dispose of them?
回答1:
A couple of things spring to mind:
- You may be holding on to a reference to an object and it's not cleaned up by garbage collection. If the class that is doing the work is a singleton, this is a very common problem.
- Make sure you call close() on any IO classes that you are using (like the BufferedInputSteam).
回答2:
Make sure your object is dereferenced once you've sent it, as remaining references would keep your image in memory. You can do that by setting all instances of that object to null
.
Additionally, calling flush()
and close()
when you're done can greatly help your memory usage.
I hope this helps!
回答3:
You haven't shown us all your method, but you've may have the large-memory local variables in scope while waiting for the next image.
Try this:
// after you've finished with the input, dereference the memory-heavy objects...
byteArray = null;
byteArrayI = null;
Also, you can "nudge" the JVM to garbage collect (you can't make it garbage collect) by calling System.gc()
and yielding the thread. If nulling alone doesn't work, try adding this
System.gc(); // "suggest" garbage collection to execute
Thread.yield(); // I have seen this encourage garbage collection to execute
回答4:
I'm willing to bet that Connection
holds an ObjectOutputStream
. If that's true, then you need to call reset()
on that stream.
回答5:
I commented but making it as an answer too.
When you create in-memory BufferedImage
s, you have to call flush()
on them when you done with them.
I am strongly suspicious your memory leak came from that.
And, as Malached said, make sure everything(BufferedImages, I/O references, and so on) not be left with any kind of references for gc
works for them.
System.gc()
is not a solution if the situation is not that your physical memory is really smaller than your memory-leak-free
program so you have to try it before the gc
works by himself.
来源:https://stackoverflow.com/questions/11956377/java-sockets-everything-written-stays-in-memory