4 Replies Latest reply on Mar 11, 2008 2:44 PM by anil.saldhana

    ClassLoader leak through TimedCachePolicy.resolutionTimer

    huuskart

      As far as I can see, a ClassLoader leak can occur through org.jboss.util.TimedCachePolicy.resolutionTimer, preventing ClassLoader and classes from unloading when an EAR is undeployed.

      I have debugged undeploy problem in my EAR with jmap -dump and jhat, and one of the reasons preventing ClassLoader from unloading is this path I see in jhat:

      Static reference from org.jboss.util.TimedCachePolicy.resolutionTimer (from class org.jboss.util.TimedCachePolicy) :
      --> java.util.Timer@0x2aa6b49830 (40 bytes) (field thread:)
      --> java.util.TimerThread@0x2aa6ac8b58 (173 bytes) (field contextClassLoader:)
      --> org.jboss.web.tomcat.service.WebAppClassLoader@0x2aa69dc338 (296 bytes) (field parent:)
      --> java.net.FactoryURLClassLoader@0x2aa69b5498 (123 bytes) (field parent:)
      --> org.jboss.mx.loading.UnifiedClassLoader3@0x2aa5ef3ec0 (203 bytes)

      The Timer object in the trace has only one TimedCachePolicy job in its queue, and that object is referenced from

      org.jboss.security.plugins.JaasSecurityManager@0x2aa6cd0fb0 (103 bytes) : field domainCache
      org.jboss.security.plugins.SecurityDomainContext@0x2aa6cd0f90 (32 bytes) : field authenticationCache

      So I'm guessing that this happens: when I first access my web application requiring authentication, JBoss creates the Timer needed to clean authCache and domainCache. This Timer is created from the context of my web app -> the TimerThread java.util.Timer creates inherits the current context ClassLoader, that is my ClassLoader. Boom.

      As a side issue, a peculiar thing is that I have disabled authenticationCache with

      0

      for JaasSecurityManagerService. Even more peculiar, the authenticationCache actually does contain the principal and credentials I used to log in to the web app. That is, authCache can't be disabled the way it is advertised.

      A possible work around is to access something else, like jmx-console first, causing the Timer to be created in that context. I'll try that shortly.


      There is also another ClassLoader leak that comes from Tomcat. See https://issues.apache.org/bugzilla/show_bug.cgi?id=44389

        • 1. Re: ClassLoader leak through TimedCachePolicy.resolutionTime
          huuskart

          Forgot to say: JBoss 4.2.1.GA, JDK 1.6.0_04.

          • 2. Re: ClassLoader leak through TimedCachePolicy.resolutionTime
            huuskart

            There is another, perhaps theoretical leak possibility JBoss authentication cache implemented using TimedCachePolicy. This is because entries in TimedCachePolicy are not purged from the cache until they are fetched from the cache, and are then noticed as expired. The leak occurs when:

            1. I login to web application using some credentials.

            2. This information is entered in the authentication cache. The login credentials involve a LoginContext object that has reference to the web app ClassLoader.

            3. I undeploy.

            4. I never ever again login using the same credentials.

            When same credentials are not used, they will not be fetched from auth cache, therefore never seen as expired and never purged: the ClassLoader is leaked through the stuff entered in the cache.

            This can be worked around by flushing the cache. I guess JBAS-4752 sort of solves this. However, I think the cache should be purged also when web application is undeployed.

            • 3. Re: ClassLoader leak through TimedCachePolicy.resolutionTime
              huuskart

              I tested with this patch to TimedCachePolicy. Yay, undeploy now works!

              --- TimedCachePolicy.java
              +++ TimedCachePolicy.java
              @@ -77,7 +77,17 @@ public class TimedCachePolicy
               public Object getValue();
               }
              
              - protected static Timer resolutionTimer = new Timer(true);
              + protected static Timer resolutionTimer;
              + static {
              + ClassLoader cl = Thread.currentThread().getContextClassLoader();
              + try {
              + Thread.currentThread().setContextClassLoader(
              + TimedCachePolicy.class.getClassLoader());
              + resolutionTimer = new Timer(true);
              + } finally {
              + Thread.currentThread().setContextClassLoader(cl);
              + }
              + }
              
               /** The map of cached TimedEntry objects. */
               protected Map entryMap;
              @@ -223,6 +233,8 @@ public class TimedCachePolicy
               entry = (TimedEntry) value;
               }
               entry.init(now);
              + if (! entry.isCurrent(now))
              + return;
               entryMap.put(key, entry);
               }
               /** Remove the entry associated with key and call destroy on the entry
              


              • 4. Re: ClassLoader leak through TimedCachePolicy.resolutionTime
                anil.saldhana

                War undeployment as well as session invalidation should be flushing the cache.