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