Details
Description
I have a servlet that is writing a 4mb response. The response is held in memory as a String and the code simple does write(myString.getBytes()).
The myString.getBytes() causes a 4mb byte array to be allocate and the data is copied into the array. The problem is the write call does the following:
public void write(byte[] b) throws IOException
{ _buf.wrap(b); write(_buf); }And buffer wrap does the following:
public void wrap(byte[] b)
{ if (isReadOnly()) throw new IllegalStateException(__READONLY); if (isImmutable()) throw new IllegalStateException(__IMMUTABLE); _bytes=b; setGetIndex(0); setPutIndex(b.length); }This causes the output stream to hold on to the last byte array written. In my case that is 4m for each of my 3000 connections.
Here is the full reference graph from yourkit:
"Name","Retained Size","Shallow Size"
"byte[3703132]","3703144","3703144"
"_bytes of org.mortbay.io.ByteArrayBuffer","3703200","56"
"_buf of org.mortbay.jetty.HttpConnection$Output","3703256","56"
"_out of org.mortbay.jetty.HttpConnection","3705144","104"
"_connection of org.mortbay.jetty.nio.SelectChannelConnector$ConnectorEndPoint","3709968","64"
"[2985] of java.lang.Runnable[3000]","1886724728","12016"
"_jobs of org.mortbay.thread.QueuedThreadPool","1886728176","128"
"this$0 of org.mortbay.thread.QueuedThreadPool$PoolThread [Stack Local, Thread, Monitor Used] "4353837@qtp-27187756-191"","2240","112"
I worked around this by writing byte[0] after my byte array.
rewrap with NO_BYTES after flush