Issue Type: Bug Bug
Assignee: Remy Maucherat
Created: 15/Jun/12 6:01 AM
Description:

org.apache.jasper.runtime.PerThreadTagHandlerPool is leaking memory because reuse() does not call instanceManager.destroyInstance(handler) when the pool is full. This happens if the number of nested tags of the same instance > Constants.MAX_POOL_SIZE ( or OPTION_MAXSIZE if set)

The instance manager in as 7.1.x implemented by org.jboss.as.web.deployment.WebInjectionContainer contains a map which holds references to the tag instances and as these are never removed the map grows over time until the heap is exhausted.

It is worth listing three possible workarounds before I go on to the fix:
1. Disable the instance manager by setting the system property org.apache.jasper.Constants.USE_INSTANCE_MANAGER_FOR_TAGS=false

2. Disable tag pooling in the jboss configuration (not tried this personally) - see post by jaikiran pai: https://community.jboss.org/thread/174669

3. Set the pool size to be greater than the maximum level of nesting by setting the system property org.apache.jasper.Constants.MAX_POOL_SIZE. Not ideal as there is no guarantee that this won't be exceeded and memory will still leak.

Looking at the commit history of PerThreadTagHandlerPool I can see that in revision 1697 the code that deals with getting and releasing tags via the instance manager was copied from TagHandlerPool, but the code in the reuse() method of TagHandlerPool was not copied and in fact the instance manager code was removed from TagHandlerPool. So it looks like both classes have this issue. I am assuming that we should always call instanceManager.destroyInstance(handler) when releasing a tag?

I have a simple test war that reproduces the problem and I have reintroduced the call to instanceManager.destroyInstance(handler) in PerThreadTagHandlerPool and it fixes the leak.

I will attach both war and patch to the issue.

I am curious as to why the try/catch around instanceManager.destroyInstance(handler) in release() is ignoring the exceptions that can be thrown? I would have thought that either the specific exceptions should be caught, which would allow runtime exceptions to propagate (perhaps undesirable) or it should log whatever exception is caught as a warn or debug message? Anyway not my call, so I have just copied the code verbatim from release().

Project: JBoss Web
Priority: Major Major
Reporter: Martin Ball
Security Level: Public (Everyone can see)
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators.
For more information on JIRA, see: http://www.atlassian.com/software/jira