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.
The behavior may not suit you, but is as intended. Feel free to customize it if you have different needs.
(In reply to comment #1) > The behavior may not suit you, but is as intended. Feel free to customize it if > 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?
turn off tag pooling.
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 least.
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.
Please see bug# 33810. It looks like this problem is a "side-effect" of fix for 33810.
This bug resulted in a about 4 months' intermittent downtime on http://issues.apache.org/jira until we discovered this report. See: http://marc.theaimsgroup.com/?t=114672636400005&r=1&w=2
Using sensibly written software helps. It should be obvious reading the API that using large body tags is going to be a huge problem.
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.
Note: setting -Dorg.apache.jasper.runtime.BodyContentImpl.LIMIT_BUFFER=true helps only for Tomcat 5.5.15 and above.
As Jeff notes, the option -Dorg.apache.jasper.runtime.BodyContentImpl.LIMIT_BUFFER=true is available in 5.5.15 onwards.
*** Bug 43925 has been marked as a duplicate of this bug. ***