Overview

JSP Tag Pooling Memory Leaks

1 Comment

JSP custom tags were once widely used, but even still nowadays they find their way into projects. Not to mention the masses of production code using them. And almost all projects I have looked at using custom tags had the same issue. When writing JSP custom tags you have to remember the lifecycle model of a custom tag, because the container will typically pool tag instances. This is allowed and recommended by the specification, but can create lots of trouble when the tag is incorrectly written. Storing big objects in the tag instance will create a memory leak that can make your server go boom (or nothing happens because your tag pool is small and the instance is almost al time in use).Typically this sneaks by unnoticed in development environment.

The code causing this problem looks typically like this one here:

public class MyTag extends TagSupport {
  public Object leak;
  public int doStartTag(){
    leak = new BigObject();
  }
}

This is a problem, because the lifecycle of a pooled tag looks like this:

  1. load class
  2. create instance
  3. invoke setPageContext()
  4. invoke setters
  5. call doStartTag
  6. call possibly other tag methods depending on the tag type and return values
  7. call doEndTag()
  8. put instance in pool

when the same tag is re-requested it may start at step 3. If in the above example this tag is pooled lets say with 10 instances and 10 simultaneous requests, 10 instances are created in the pool. But after that only a few requests come in. But still 10 instances of the tag are in the pool and contain reference to the BigObject. This is a memory leak.

To avoid this always null out “transient” instance variables of the class and reload them either in setPageContext() or doStartTag(). Also note that the code inside the constructor might only be run once per tag, even when the tag is used on hundreds of pages. The amount of tag instances created (and thus also the amount of constructors invoked) depends on the container and pool settings and on the serverload.

public class MyTag extends TagSupport {
  public Object noLeak;
 
  public void setPageContext(PageContext pc){
    noLeak = new BigObject();
  }
 
  public int doStartTag(){
  }
 
  public void doEndTag(){
    noLeak = null;
  }
}

Other alternatives are to improve code design and make variables as local as possible.
A relates problem is that you might find values in your tag that you don’t expect. Lets say a property is set when a certain parameter has a specific value. Now that condition was true, so the property holds an object that is not nulled out. The next usage of that tag will find the object even though the condition on the parameter is not set. This can really mess up your logic.

Kommentare

  • Slava

    17. June 2014 von Slava

    This issue is being discovered by different people who start working with JSP custom tags. For example here: http://stackoverflow.com/questions/616064/jsp-tag-lifecycle.

    I would recommend to clean the state variables not in doEndTag() but in release() method as it exists specifically for this purpose.

    Another solution: instead of creating state holding variable you can use setValue/getValue methods from TagSupport. It will put all of them into the HashTable and clean it in the end of cycle in release() method.

Comment

Your email address will not be published. Required fields are marked *