Bug 37793

Summary: org.apache.jasper.runtime.BodyContentImpl doesn't reset the 'cb' character array, causes memory leak
Product: Tomcat 5 Reporter: Puhong You <pyou>
Component: JasperAssignee: Tomcat Developers Mailing List <dev>
Severity: normal CC: apache.org, brian.remmington, jefft, pyou
Priority: P2    
Version: 5.5.9   
Target Milestone: ---   
Hardware: PC   
OS: Windows 2000   
Attachments: The attachment contains profiler snapshots showing char[] holding upto 205MB finally causing the container to go out of memory

Description Puhong You 2005-12-05 18:37:12 UTC
In the constructor of BodyContentImpl, member variable 'cb' is initialized via

	cb = new char[bufferSize];

with default buffer size = 512. This character array grows at run time to 
accommodate the body content. In our case, one of our pages produces body 
content over 4 mega characters, resulting the 'cb' array to be expanded to over 
8 mega characters.

The problem is that this huge array never gets reset due to the object pooling 
implementation in Jasper (JspFactoryImpl maintains a pool of PageContextImpl 
objects. Each PageContextImpl object maintains an array of BodyContentImpl 
objects), so the memory it consumed is never returned to the heap.

One suggestion is to reset the 'cb' character array in the setWriter() method.
Comment 1 Remy Maucherat 2005-12-05 18:39:53 UTC
The behavior may not suit you, but is as intended. Feel free to customize it if
you have different needs.
Comment 2 Puhong You 2005-12-05 18:52:05 UTC
(In reply to comment #1)
> The behavior may not suit you, but is as intended. Feel free to customize it 
> you have different needs.

By 'customize' it, do you mean to modify the source code and recompile jasper-
runtime.jar? This doesn't really work for us, since our customers run our 
software on Tomcat 5 and it's odd that we have to ship a new jasper-runtime.jar 
to each and every one of them.

Can you share your rationale for the decision to not reset the 'cb' array? Is 
there a configuration option to change the behavior?
Comment 3 Tim Funk 2005-12-05 19:11:21 UTC
turn off tag pooling. 
Comment 4 Puhong You 2005-12-05 21:28:34 UTC
Turning off tag pooling (i.e, set 'enablePooling' initial parameter to 'false' 
for the JSP page compiler and execution servlet) doesn't turning off the 
PageContext pooling in JspFactoryImpl class. The 'USE_POOL' is set to 'true' 
and can not be overwritten:

   private static final boolean USE_POOL = true;

I am really interested to know the rationale behind the decision of not re-
sizing the 'cb' character array on setWriter(). If the 'cb' array grows huge by 
one tag evaluation, its massive memory block will not be returned to heap until 
the Jasper runtime is restarted. The merit of this behavior is questionable at 
Comment 5 Tino Schwarze 2005-12-14 23:30:13 UTC
I'm seeing the same problem and are in the process of hunting down several
memory "leaks". Patches against current Tomcat 5.5 SVN will follow.
Comment 6 Purush Rudrakshala 2005-12-18 16:30:46 UTC
Please see bug# 33810. It looks like this problem is a "side-effect" of fix for
Comment 7 Jeff Turner 2006-06-02 00:17:31 UTC
This bug resulted in a about 4 months' intermittent downtime on
http://issues.apache.org/jira until we discovered this report. See:

Comment 8 Remy Maucherat 2006-06-02 09:30:21 UTC
Using sensibly written software helps. It should be obvious reading the API that
using large body tags is going to be a huge problem.
Comment 9 Vandana 2006-08-18 21:59:41 UTC
Created attachment 18735 [details]
The attachment contains profiler snapshots showing char[] holding upto 205MB finally causing the container to go out of memory

We are struggling with a similar issue with tomcat 5.0.30 and we are not in a
position to upgrade the version .

Our JSP pages are large and we are able to bring tomcat down very quickly with
just 3-4 sessions browsing couple of pages.Memory is mostly held by char[]
BodyContentImpl and GC tries to clean some memory but eventually the system
goes out of memory as GC is not able to free anything held by char[].

The problem is seen in prod where memory is very high .We replicated in dev
with tomcat5.0.30 running with the following settings:

 JAVAOPTS: -server -Djava.awt.headless=true -Xms64m -Xmx256m
-Xloggc:logs/gc.out -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:NewSize=8m
-XX:MaxNewSize=128m -XX:+DisableExplicitGC

Profiler used in JProfiler. Will appreciate inputs to resolve this issue.
Breaking down JSP pages can be looked at in the future but would involve
significant effort/time/funding and at this point we need to resolve the issue
without breaking down the JSP pages since the app is already in prod and is
falling apart because of this problem.
Comment 10 Jeff Turner 2006-10-11 17:52:51 UTC
Note: setting -Dorg.apache.jasper.runtime.BodyContentImpl.LIMIT_BUFFER=true
helps only for Tomcat 5.5.15 and above.
Comment 11 Mark Thomas 2006-11-06 18:45:35 UTC
As Jeff notes, the option
-Dorg.apache.jasper.runtime.BodyContentImpl.LIMIT_BUFFER=true is available in
5.5.15 onwards.
Comment 12 Tim Funk 2008-04-03 04:07:15 UTC
*** Bug 43925 has been marked as a duplicate of this bug. ***