This is actually a bug for version 1.0.6 (but I couldn't select that version because it wasn't listed). WHAT IS IT?: All evaluated expressions are added to the ELEvaluator's sCachedExpressionStrings map and never removed. This causes a memory leak which can eventually cause running programs to crash due to an OutOfMemoryError. WHERE IS IT?: org.apache.taglibs.standard.lang.jstl.ELEvaluator.parseExpressionString(String) TO REPRODUCE: Write a simple page that uses a JSTL tag, give it a different dynamically-generated expression as an attribute value and refresh the page several times. Eventually you will see the memory climb (through profiling, system logs or by your process exiting with an OutOfMemoryError). A POSSIBLE FIX: A possible fix would be to use a last-recently-used cache (such as Java 1.4's LinkedHashMap) to ensure that items do not remain in this cache indefinitely.
Just for the record, there is a thread going on the devs list about how to solve this issue: http://nagoya.apache.org/eyebrowse/BrowseList?listName=taglibs-dev@jakarta.apache.org&by=thread&from=903348 BTW, I have some suggesions to make, but will do it from home (as my email client is not configured here at work to send the proper From: id). Meanwhile, I would suggest Daryl to use this bug for uploading anything. -- Felipe
Created attachment 13161 [details] The String cache size of my application after ~ 35 mins.
Created attachment 13162 [details] The String cache hit rate of my application after ~ 35 mins.
Created attachment 13163 [details] The String cache calls by my application after ~ 35 mins.
Created attachment 13189 [details] eval() calls non-expressions vs. expressions ratio in custom tags
Created attachment 13190 [details] eval() calls non-expressions vs. expressions ratio in JSTL tags
Created attachment 13191 [details] String cache size with indexOf("${") bypass enabled.
Created attachment 13192 [details] String cache calls with indexOf("${") bypass enabled (in custom tags).
Created attachment 13193 [details] String cache hit-rate with indexOf("${") bypass enabled (in custom tags).
*** Bug 30136 has been marked as a duplicate of this bug. ***
Created attachment 19542 [details] SPI like fix for this issue, 17700 and 32311 Patch attached which creates a pluggable system via Java system properties to allow for different types of caches to resolve the problems expressed in this issue, and in #32311 and #17700. The Java system property configuration seems weak, but I'm not sure what you could replace it with without changing a bunch of code. Completely untested :) Will aim to test it next week.
There are other locations that might require the caching strategy. tag.common.fmt would seem to have a few.
Created attachment 20701 [details] Updated version of the caching factory patch This is a tested version of the original patch, with a few bugs fixed. Things should behave the same as before by default, but you can either turn on caching (forever) or turn off caching (null) to ease some of these issues. Alternatively you could write your own cache. For DateFormat for example, speed improves 30% if you turn caching of DateFormat objects on. One issue is that for ELEvaluator parsing, I've removed the synchronization that was being done. I need to change the patch so that that is still there.
Scratch the synchronization comment. Had been a bit since I'd looked at the code. The ForeverCache maintains the synchronization, so it's at a lower level. The patch has a bug in the Resources class where it still uses format(String, Object[]) and hasn't had the 'res' deleted to make it use format(Object[]). Even with that fix, I can't make a fmt:message faster.
Created attachment 20866 [details] Patch implementing Kris's mBypassCache suggestion Here's a patch that implement's Kris's mBypassCache.
Also reported to EL as: http://issues.apache.org/jira/browse/EL-1
Created attachment 20868 [details] Slight modification of Bjorn's patch I've attached a slight modification to Bjorn's patch - adding a note to the javadoc and restricting the change to the ELEvaluator class.
Created attachment 20887 [details] Implementation of LRU cacheing strategy After doing a ton of research, I found that someone had actually branched 1.0.6 and implemented a LRU-based cacheing strategy, with the size of the cache definable by the user in a context initialization parameter. The implementation uses a set of classes borrowed from Commons Collections, but does not introduce Collections as a dependancy. I found this code in the following branch: http://svn.apache.org/repos/asf/jakarta/taglibs/proper/standard/branches/STANDARD_1_0_BRANCH The default cache size is 100 entries. It'd probably be wise to experiment with this value in one's own environment before settling on an optimum size. After a conversation with Henri on the taglibs dev list, I've gone ahead and adapted the patch to work with 1.1. I've already run it through the taglibs unit test suite -- all tests passed. This patch also fixes the issue whereby cacheing could not be turned off.
And for the sake of completeness, here's a link to the new mailing list discussion on this bug: http://mail-archives.apache.org/mod_mbox/jakarta-taglibs-dev/200709.mbox/browser
The 1.0.6 fix has been applied to the 1.1 branch.