Bug 30136 - Memory leak in JSTL ELEvaluator cache
Summary: Memory leak in JSTL ELEvaluator cache
Status: RESOLVED DUPLICATE of bug 31789
Alias: None
Product: Taglibs
Classification: Unclassified
Component: Standard Taglib (show other bugs)
Version: 1.0.4
Hardware: All All
: P3 normal with 3 votes (vote)
Target Milestone: ---
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-07-16 01:32 UTC by Knut Forkalsrud
Modified: 2005-02-23 10:35 UTC (History)
1 user (show)



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Knut Forkalsrud 2004-07-16 01:32:13 UTC
We're using version 1.0.2, but the source code for newer releases have no change
in this area.  The problem is the expression evaluator:

jakarta-taglibs/standard/src/org/apache/taglibs/standard/lang/jstl/ELEvaluator.java

By default it sets up a hash map to cache the values of each expression it
evaluates, but there is no upper limit on how large the cache is allowed to
grow.  In our case the application grows approx 500 MByte in a 24 hour period. 
I have searched for other mentionings of the same problem and found only one:

http://www.mail-archive.com/taglibs-user@jakarta.apache.org/msg07007.html

For now I have set up a bit of a hack to work around the issue.  Since there is
no easy way to access this class from outside the package I had to make a new
class in a package with the same name.  This is a subclass of
java.util.LinkedHashMap that won't grow indefinitely.  I just swap it in
replacing the existing ELEvaluator.sCachedExpressionStrings

I think the standard cache in ELEvaluatorCache should have an upper size limit.





import org.apache.taglibs.standard.lang.support.ExpressionEvaluatorManager;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.jsp.JspException;
import org.apache.log4j.Logger;

/**
 * @author Knut Forkalsrud
 */
public class EvaluatorCache
    extends LinkedHashMap
{
    int maxEntries;

    public EvaluatorCache(int maxEntries) {
        super((int)((float)maxEntries / 0.75), (float)0.75, true);
        this.maxEntries = maxEntries;
    }

    protected boolean removeEldestEntry(Map.Entry eldest) {
        return size() > maxEntries;
    }

    public static void replaceCacheImpl(int maxEntries) {
        ELEvaluator.sCachedExpressionStrings
            = Collections.synchronizedMap(new EvaluatorCache(maxEntries));
    }
}

// eof
Comment 1 Dhiru Pandey 2005-02-23 19:35:06 UTC

*** This bug has been marked as a duplicate of 31789 ***