Uploaded image for project: 'JBoss Web'
  1. JBoss Web
  2. JBWEB-269

Memory Leak when Custom Tags Throw Runtime Exception

    Details

    • Type: Bug
    • Status: Open (View Workflow)
    • Priority: Minor
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: Tomcat
    • Labels:
      None
    • Steps to Reproduce:
      Hide

      Deploy the attached tagLeakTest.war.
      Run the jmeter script.
      Observe the growing number of instances of com.test.tag.SimpleTag/com.test.tag.SimpleExceptionTag/associated interceptor classes using visualvm or other profiler.

      Show
      Deploy the attached tagLeakTest.war. Run the jmeter script. Observe the growing number of instances of com.test.tag.SimpleTag/com.test.tag.SimpleExceptionTag/associated interceptor classes using visualvm or other profiler.
    • Workaround Description:
      Hide

      Disable the instance manager by setting the system property org.apache.jasper.Constants.USE_INSTANCE_MANAGER_FOR_TAGS=false

      Show
      Disable the instance manager by setting the system property org.apache.jasper.Constants.USE_INSTANCE_MANAGER_FOR_TAGS=false

      Description

      There appears to be a bug in org.apache.jasper.compiler.Generator which in cases where a custom tag throws a runtime exception will lead to a memory leak. The problem is that the code generated only wraps the call to the taghandler pool reuse() method in a try/finally block if the tag implements javax.servlet.jsp.tagext.TryCatchFinally. So for any tag that does not implement TryCatchFinally if a runtime exception occurs reuse() is never called, which means the tag that threw the exception and any tags it is nested within are not returned to the pool, so new instances are created every request and the instance manager is left holding references to the associated interceptor/injection instances.

      The fix is to always wrap the code in try/finally so that reuse()/release() is always called and then optionally add the catch block/calls to the TryCatchFinally methods doCatch/doFinally when required.

      I have tested the leak/a fix against both JBoss Web 7.0.17.FINAL and 7.2.0.Final. I will attach my test war/jmeter project which demonstrates the issue along with my patch. When running the test on unpatched code we observe a continual increase in the instances of com.test.tag.SimpleTag and com.test.tag.SimpleExceptionTag, with the patched code the issue no longer occurs. The test also contains calls to jsps which do not throw exceptions/throw exceptions but implement TryCatchFinally, this is to check that the patched code still generates the try/catch/finally properly and still behaves as expected in normal operation.

      We can verify the cause of the problem by debugging and adding a breakpoint to org.apache.jasper.runtime.PerThreadTagHandlerPool.reuse(Tag handler) and then hitting the test page http://hostname:port/tagLeakTest/nestedtagWithException.jsp, without the patch reuse() will not be called, with the patch it will.

        Gliffy Diagrams

          Attachments

          1. Generator.java.patch
            4 kB
          2. tagLeakTest.jmx
            16 kB
          3. tagLeakTest.zip
            24 kB

            Activity

              People

              • Assignee:
                rmaucher Remy Maucherat
                Reporter:
                martin.ball Martin Ball
              • Votes:
                0 Vote for this issue
                Watchers:
                2 Start watching this issue

                Dates

                • Created:
                  Updated: