ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button
Article:
  Two Servlet Filters Every Web Application Should Have
Subject:   GZIP memory leak and content length problems
Date:   2004-08-18 07:29:21
From:   krem
Hi,


I found few issues using the GZIP compression filter. I'll show the solutions that worked for me.


I am using Jetty/4.2.21 WEB server and servlet container running on Java VM (build 1.4.2_05-b04).
The OS is Win 2000.


After deploying the GZIP compression filter and running my stress test I found a strange memory leak.
The memory usage of the Java VM started growing rapidly. No java.lang.OutOfMemoryError has been thrown after the VM memory reached the maximum heap size (which was set to 64MB). After the memory usage reached about 600MB I had to stop the stress test because my OS complained about low virtual memory. I suppose there is a memory leak in the native gzip library which is used by the VM.


I am not sure if this is a general issue or it is just related to the server I am using, but I found a solution.


I have rewritten the doFilter method as follows:




public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
if (req instanceof HttpServletRequest) {

HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String ae = request.getHeader("accept-encoding");
if (ae!=null && ae.indexOf("gzip")!=-1) {
GZIPResponseWrapper wrappedResponse = new GZIPResponseWrapper(response);
try {
chain.doFilter(req, wrappedResponse);
}
catch (ServletException ex) {throw ex;}
catch (IOException ex) {throw ex;}
catch (Exception ex) {throw new ServletException(ex);} // this is in case a Servet caused an internal error
finally {
wrappedResponse.finishResponse();
}
}
else chain.doFilter(req, res);

}
}




I am using the finally statement to ensure that the finishResponse() method gets called in all cases.


Second, I have rewritten the GZIPResponseStream.close() method as follows:




public void close() throws IOException {
if (closed) throw new IOException("This output stream has already been closed");
//
gzipstream.finish();
gzipstream.flush();
gzipstream.close(); //!!!
//
byte[] bytes = baos.toByteArray();
response.setContentLength(bytes.length);
response.addHeader("Content-Encoding","gzip");
output.write(bytes);
output.flush();
output.close();
closed = true;
}




Closing the gzipstream fixed the memory leak.


The second issue was about the content length. The browser acted strangely. Data seemed to be corrupted. Sometimes the css styles disapeared, sometimes not.


The resolution is in the GZIPResponseStream.close() method as written above. I had to change the line:



response.addHeader("Content-Length", Integer.toString(bytes.length));


to



response.setContentLength(bytes.length);



I hope this post is somehow helpful and I really hope somebody understood my poor English:)


Have a nice day,
krem.


1 to 3 of 3
  1. GZIP memory leak and content length problems
    2008-11-08 21:05:50  corlettk [View]

  2. GZIP memory leak and content length problems
    2007-07-20 07:26:15  ManfredJS [View]

  3. GZIP memory leak and content length problems
    2004-10-13 05:57:23  saikinnera [View]

    • GZIP memory leak and content length problems
      2006-07-23 23:26:04  CheenuInventor [View]

      • GZIP memory leak and content length problems
        2007-01-18 05:49:27  ShriniMailNSrinivasan@gmail.com [View]

1 to 3 of 3