View Javadoc

1   /*
2    * $Id: LoggerReferenceHandler.java 21603 2011-03-23 13:41:33Z aperepel $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.module.logging;
12  
13  import java.lang.ref.PhantomReference;
14  import java.lang.ref.Reference;
15  import java.lang.ref.ReferenceQueue;
16  import java.util.Map;
17  import java.util.concurrent.Executors;
18  import java.util.concurrent.ThreadFactory;
19  
20  /**
21   *  A utility class cleaning up the logger repositories once the classloader for the application went
22   *  out of scope and became eligible fot GC (e.g. app redeployed or undeployed).
23   */
24  public class LoggerReferenceHandler
25  {
26  
27      // note that this is a direct log4j logger declaration, not a clogging one
28      protected org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(getClass());
29  
30      public LoggerReferenceHandler(final String threadName,
31                                    final ReferenceQueue<ClassLoader> referenceQueue,
32                                    final Map<PhantomReference<ClassLoader>, Integer> references,
33                                    final Map<Integer, ?> loggerRepository)
34      {
35          Executors.newSingleThreadExecutor(new ThreadFactory()
36          {
37              public Thread newThread(Runnable r)
38              {
39                  final Thread thread = Executors.defaultThreadFactory().newThread(r);
40                  thread.setName(threadName);
41                  // CRITICAL - do NOT try to set this thread as a daemon or lower its priority,
42                  // as it may never get scheduled by JVM then, really tricky
43                  return thread;
44              }
45          }).submit(new Runnable()
46          {
47              public void run()
48              {
49                  while (!Thread.currentThread().isInterrupted())
50                  {
51                      try
52                      {
53                          final Reference<? extends ClassLoader> reference = referenceQueue.remove();
54                          logger.debug("Cleaning up the logging hierarchy");
55                          final Integer classLoaderHash = references.get(reference);
56                          loggerRepository.remove(classLoaderHash);
57                      }
58                      catch (InterruptedException e)
59                      {
60                          Thread.currentThread().interrupt();
61                      }
62                      catch (RuntimeException rex)
63                      {
64                          logger.error("Zombies detected, run for your life", rex);
65                      }
66                  }
67              }
68          });
69      }
70  }