[JBoss JIRA] Created: (NETTY-315) Memory Leak when HttpContentCompressor is in server pipeline
Greg Haines (JIRA)
jira-events at lists.jboss.org
Thu May 13 16:06:26 EDT 2010
Memory Leak when HttpContentCompressor is in server pipeline
------------------------------------------------------------
Key: NETTY-315
URL: https://jira.jboss.org/jira/browse/NETTY-315
Project: Netty
Issue Type: Bug
Components: Handler
Affects Versions: 3.2.0.CR1
Environment: Linux version 2.6.18-164.el5 (CentOS)
Java HotSpot(TM) 64-Bit Server VM (build 16.0-b13, mixed mode)
Reporter: Greg Haines
Assignee: Trustin Lee
Priority: Critical
I'm encountering a crippling memory leak when a client request has the "ACCEPT-ENCODING: gzip" header and requests numerous large files from my Netty-based HTTP server. It works for a few thousand requests then inevitably bombs with an java.lang.OutOfMemoryError: Java heap space. I tried playing with the GC tuning options to no avail.
I ran the resulting heap dump through Eclispe Memory Analysis Tool and this was the result:
The class "org.jboss.netty.channel.AbstractChannel", loaded by "sun.misc.Launcher$AppClassLoader @ 0xb6c345f0", occupies 1,555,736,280 (99.95%) bytes. The memory is accumulated in one instance of "org.jboss.netty.util.internal.ConcurrentHashMap$Segment[]" loaded by "sun.misc.Launcher$AppClassLoader @ 0xb6c345f0".Keywords
org.jboss.netty.util.internal.ConcurrentHashMap$Segment[]
sun.misc.Launcher$AppClassLoader @ 0xb6c345f0
org.jboss.netty.channel.AbstractChannel
It appears that the ConcurrentHashMap variable called allChannels is the culprit. All the values are of EmbeddedChannels.
Here is my setup:
Server startup command:
java -server -Xmx1536M -Xms1536M -Xmn512M -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:SurvivorRatio=8 -XX:TargetSurvivorRatio=90 -XX:MaxTenuringThreshold=31 -XX:+AggressiveOpts -XX:+UseFastAccessorMethods -jar uvs-1.0-SNAPSHOT.jar
Server pipeline factory:
final ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("decoder", new HttpRequestDecoder());
pipeline.addLast("encoder", new HttpResponseEncoder());
pipeline.addLast("deflater", new HttpContentCompressor());
pipeline.addLast("uvsHandler", this.uvsRequestHandler); // My @Sharable handler
return pipeline;
Server handler code:
final RandomAccessFile raf = new RandomAccessFile(file, "r");
final HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
response.setHeader(LAST_MODIFIED, HttpUtils.getLastModifiedString(file));
response.setHeader(CONTENT_TYPE, TECH_BINARY_CONTENT_TYPE);
HttpHeaders.setContentLength(response, file.length());
final FileChannel fc = raf.getChannel();
response.setContent(ChannelBuffers.wrappedBuffer(fc.map(MapMode.READ_ONLY, 0, fc.size())));
final ChannelFuture future = channel.write(response);
future.addListener(new FileChannelCloseListener(fc)); // simply calls fc.close() in its operationComplete()
if (!keepAlive)
{
future.addListener(ChannelFutureListener.CLOSE);
}
Client pipeline:
final ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("codec", new HttpClientCodec());
pipeline.addLast("inflater", new HttpContentDecompressor());
pipeline.addLast("handler", this.httpResponseHandler); // My @Sharable handler
return pipeline;
Client handler code:
public void messageReceived(final ChannelHandlerContext ctx, final MessageEvent e)
{
final TDFState tdfState = (TDFState) ctx.getAttachment();
if (!tdfState.isReadingChunks())
{
final HttpResponse response = (HttpResponse) e.getMessage();
tdfState.setResponse(response);
if (response.isChunked())
{
tdfState.setReadingChunks(true);
}
else
{
final int b = response.getContent().readableBytes();
if (b > 0)
{
final ByteBuffer buf = ByteBuffer.allocate(b);
response.getContent().readBytes(buf);
}
tdfState.addBytes(b);
tdfState.requestFulfilled();
}
}
else
{
final HttpChunk chunk = (HttpChunk) e.getMessage();
if (chunk.isLast())
{
tdfState.setReadingChunks(false);
tdfState.requestFulfilled();
}
else
{
final int b = chunk.getContent().readableBytes();
final ByteBuffer buf = ByteBuffer.allocate(b);
chunk.getContent().readBytes(buf);
tdfState.addBytes(b);
}
}
}
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
More information about the netty-dev
mailing list