logging-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rpo...@apache.org
Subject svn commit: r1557654 - in /logging/log4j/log4j2/trunk: log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/Server.java src/changes/changes.xml
Date Mon, 13 Jan 2014 07:36:48 GMT
Author: rpopma
Date: Mon Jan 13 07:36:48 2014
New Revision: 1557654

URL: http://svn.apache.org/r1557654
Log:
LOG4J2-406: Unregister all log4j JMX MBeans when the LoggerContext is stopped to allow web
application classes to be GC-ed on undeploy.

Modified:
    logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
    logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/Server.java
    logging/log4j/log4j2/trunk/src/changes/changes.xml

Modified: logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java?rev=1557654&r1=1557653&r2=1557654&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
(original)
+++ logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
Mon Jan 13 07:36:48 2014
@@ -20,8 +20,6 @@ import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
 import java.io.File;
 import java.net.URI;
-import java.util.HashMap;
-import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.CopyOnWriteArrayList;
@@ -217,6 +215,9 @@ public class LoggerContext implements or
             status = Status.STOPPED;
         } finally {
             configLock.unlock();
+            
+            // in finally: unregister MBeans even if an exception occurred while stopping

+            Server.unregisterMBeans(); // LOG4J2-406
         }
     }
 
@@ -350,6 +351,12 @@ public class LoggerContext implements or
         for (final PropertyChangeListener listener : propertyChangeListeners) {
             listener.propertyChange(evt);
         }
+
+        try {
+            Server.reregisterMBeansAfterReconfigure();
+        } catch (final Exception ex) {
+            LOGGER.error("Could not reconfigure JMX", ex);
+        }
         return prev;
     }
 
@@ -382,12 +389,6 @@ public class LoggerContext implements or
          * updateLoggers(); if (old != null) { old.stop(); }
          */
 
-        try {
-            Server.reregisterMBeansAfterReconfigure();
-        } catch (final Exception ex) {
-            LOGGER.error("Could not reconfigure JMX", ex);
-        }
-
         LOGGER.debug("Reconfiguration completed");
     }
 

Modified: logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/Server.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/Server.java?rev=1557654&r1=1557653&r2=1557654&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/Server.java
(original)
+++ logging/log4j/log4j2/trunk/log4j-core/src/main/java/org/apache/logging/log4j/core/jmx/Server.java
Mon Jan 13 07:36:48 2014
@@ -62,9 +62,8 @@ public final class Server {
      * Either returns the specified name as is, or returns a quoted value
      * containing the specified name with the special characters (comma, equals,
      * colon, quote, asterisk, or question mark) preceded with a backslash.
-     *
-     * @param name
-     *            the name to escape so it can be used as a value in an
+     * 
+     * @param name the name to escape so it can be used as a value in an
      *            {@link ObjectName}.
      * @return the escaped name
      */
@@ -78,13 +77,15 @@ public final class Server {
             case '*':
             case '?':
             case '\"':
-                sb.append('\\'); // quote, star, question & backslash must be escaped
+                // quote, star, question & backslash must be escaped
+                sb.append('\\');
                 needsQuotes = true; // ... and can only appear in quoted value
                 break;
             case ',':
             case '=':
             case ':':
-                needsQuotes = true; // no need to escape these, but value must be quoted
+                // no need to escape these, but value must be quoted
+                needsQuotes = true;
                 break;
             }
             sb.append(c);
@@ -97,17 +98,26 @@ public final class Server {
     }
 
     /**
+     * Creates MBeans to instrument classes in the log4j class hierarchy and
+     * registers the MBeans in the platform MBean server so they can be accessed
+     * by remote clients.
+     * 
+     * @throws JMException if a problem occurs during registration
+     */
+    public static void registerMBeans() throws JMException {
+        final ContextSelector selector = getContextSelector();
+        registerMBeans(selector);
+    }
+
+    /**
      * Creates MBeans to instrument the specified selector and other classes in
      * the log4j class hierarchy and registers the MBeans in the platform MBean
      * server so they can be accessed by remote clients.
-     *
-     * @param selector
-     *            starting point in the log4j class hierarchy
-     * @throws JMException
-     *             if a problem occurs during registration
+     * 
+     * @param selector starting point in the log4j class hierarchy
+     * @throws JMException if a problem occurs during registration
      */
-    public static void registerMBeans(final ContextSelector selector)
-            throws JMException {
+    public static void registerMBeans(final ContextSelector selector) throws JMException
{
 
         // avoid creating Platform MBean Server if JMX disabled
         if (Boolean.getBoolean(PROPERTY_DISABLE_JMX)) {
@@ -122,16 +132,12 @@ public final class Server {
      * Creates MBeans to instrument the specified selector and other classes in
      * the log4j class hierarchy and registers the MBeans in the specified MBean
      * server so they can be accessed by remote clients.
-     *
-     * @param selector
-     *            starting point in the log4j class hierarchy
-     * @param mbs
-     *            the MBean Server to register the instrumented objects in
-     * @throws JMException
-     *             if a problem occurs during registration
+     * 
+     * @param selector starting point in the log4j class hierarchy
+     * @param mbs the MBean Server to register the instrumented objects in
+     * @throws JMException if a problem occurs during registration
      */
-    public static void registerMBeans(final ContextSelector selector,
-            final MBeanServer mbs) throws JMException {
+    public static void registerMBeans(final ContextSelector selector, final MBeanServer mbs)
throws JMException {
 
         if (Boolean.getBoolean(PROPERTY_DISABLE_JMX)) {
             LOGGER.debug("JMX disabled for log4j2. Not registering MBeans.");
@@ -143,7 +149,7 @@ public final class Server {
         final List<LoggerContext> contexts = selector.getLoggerContexts();
         registerContexts(contexts, mbs, executor);
     }
-    
+
     public static void reregisterMBeansAfterReconfigure() {
         // avoid creating Platform MBean Server if JMX disabled
         if (Boolean.getBoolean(PROPERTY_DISABLE_JMX)) {
@@ -159,31 +165,19 @@ public final class Server {
             LOGGER.debug("JMX disabled for log4j2. Not registering MBeans.");
             return;
         }
-        
-        try {
-            unregisterStatusLogger(mbs);
-            registerStatusLogger(mbs, executor);
-        } catch (Exception ex) {
-            LOGGER.error("Could not register MBeans", ex);
-        }
-
-        final ContextSelector selector = getContextSelector();
-        if (selector == null) {
-            LOGGER.debug("Could not register MBeans: no ContextSelector found.");
-            return;
-        }
 
         // first unregister the old MBeans
-        unregisterContextSelector(mbs);
-        unregisterContexts(mbs);
-        unregisterLoggerConfigs("*", mbs);
-        unregisterAsyncLoggerConfigRingBufferAdmins("*", mbs);
-        unregisterAppenders("*", mbs);
-        unregisterAsyncAppenders("*", mbs);
+        unregisterMBeans(mbs);
 
         // now provide instrumentation for the newly configured
         // LoggerConfigs and Appenders
         try {
+            registerStatusLogger(mbs, executor);
+            final ContextSelector selector = getContextSelector();
+            if (selector == null) {
+                LOGGER.debug("Could not register MBeans: no ContextSelector found.");
+                return;
+            }
             registerContextSelector(selector, mbs, executor);
             final List<LoggerContext> contexts = selector.getLoggerContexts();
             registerContexts(contexts, mbs, executor);
@@ -196,22 +190,52 @@ public final class Server {
         }
     }
 
+    /**
+     * Unregister all log4j MBeans from the platform MBean server.
+     */
+    public static void unregisterMBeans() {
+        final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+        unregisterMBeans(mbs);
+    }
+
+    /**
+     * Unregister all log4j MBeans from the specified MBean server.
+     * 
+     * @param mbs the MBean server to unregister from.
+     */
+    public static void unregisterMBeans(MBeanServer mbs) {
+        unregisterStatusLogger(mbs);
+        unregisterContextSelector(mbs);
+        unregisterContexts(mbs);
+        unregisterLoggerConfigs("*", mbs);
+        unregisterAsyncLoggerRingBufferAdmins("*", mbs);
+        unregisterAsyncLoggerConfigRingBufferAdmins("*", mbs);
+        unregisterAppenders("*", mbs);
+        unregisterAsyncAppenders("*", mbs);
+    }
+
+    /**
+     * Returns the {@code ContextSelector} of the current
+     * {@code Log4jContextFactory}.
+     * 
+     * @return the {@code ContextSelector} of the current
+     *         {@code Log4jContextFactory}
+     */
     private static ContextSelector getContextSelector() {
-        ContextSelector selector = null;
         final LoggerContextFactory factory = LogManager.getFactory();
         if (factory instanceof Log4jContextFactory) {
-            selector = ((Log4jContextFactory) factory).getSelector();
+            ContextSelector selector = ((Log4jContextFactory) factory).getSelector();
+            return selector;
         }
-        return selector;
+        return null;
     }
 
     /**
      * Unregisters all MBeans associated with the specified logger context
      * (including MBeans for {@code LoggerConfig}s and {@code Appender}s from
      * the platform MBean server.
-     *
-     * @param loggerContextName
-     *            name of the logger context to unregister
+     * 
+     * @param loggerContextName name of the logger context to unregister
      */
     public static void unregisterContext(String loggerContextName) {
         final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
@@ -222,11 +246,9 @@ public final class Server {
      * Unregisters all MBeans associated with the specified logger context
      * (including MBeans for {@code LoggerConfig}s and {@code Appender}s from
      * the platform MBean server.
-     *
-     * @param loggerContextName
-     *            name of the logger context to unregister
-     * @param mbs
-     *            the MBean Server to unregister the instrumented objects from
+     * 
+     * @param loggerContextName name of the logger context to unregister
+     * @param mbs the MBean Server to unregister the instrumented objects from
      */
     public static void unregisterContext(String contextName, MBeanServer mbs) {
         final String pattern = LoggerContextAdminMBean.PATTERN;
@@ -255,9 +277,9 @@ public final class Server {
     }
 
     /**
-     * Registers MBeans for all contexts in the list.
-     * First unregisters each context (and nested loggers, appender etc)
-     * to prevent InstanceAlreadyExistsExceptions.
+     * Registers MBeans for all contexts in the list. First unregisters each
+     * context (and nested loggers, appender etc) to prevent
+     * InstanceAlreadyExistsExceptions.
      */
     private static void registerContexts(final List<LoggerContext> contexts, final
MBeanServer mbs,
             final Executor executor) throws InstanceAlreadyExistsException, MBeanRegistrationException,
@@ -266,10 +288,10 @@ public final class Server {
         for (final LoggerContext ctx : contexts) {
             // first unregister the context and all nested loggers & appenders
             unregisterContext(ctx.getName());
-            
+
             final LoggerContextAdmin mbean = new LoggerContextAdmin(ctx, executor);
             register(mbs, mbean, mbean.getObjectName());
-            
+
             if (ctx instanceof AsyncLoggerContext) {
                 RingBufferAdmin rbmbean = AsyncLogger.createRingBufferAdmin(ctx.getName());
                 register(mbs, rbmbean, rbmbean.getObjectName());
@@ -285,8 +307,7 @@ public final class Server {
         unregisterAllMatching(ContextSelectorAdminMBean.NAME, mbs);
     }
 
-    private static void unregisterLoggerConfigs(final String contextName,
-            final MBeanServer mbs) {
+    private static void unregisterLoggerConfigs(final String contextName, final MBeanServer
mbs) {
         final String pattern = LoggerConfigAdminMBean.PATTERN;
         final String search = String.format(pattern, contextName, "*");
         unregisterAllMatching(search, mbs);
@@ -298,29 +319,25 @@ public final class Server {
         unregisterAllMatching(search, mbs);
     }
 
-    private static void unregisterAppenders(final String contextName,
-            final MBeanServer mbs) {
+    private static void unregisterAppenders(final String contextName, final MBeanServer mbs)
{
         final String pattern = AppenderAdminMBean.PATTERN;
         final String search = String.format(pattern, contextName, "*");
         unregisterAllMatching(search, mbs);
     }
 
-    private static void unregisterAsyncAppenders(final String contextName,
-            final MBeanServer mbs) {
+    private static void unregisterAsyncAppenders(final String contextName, final MBeanServer
mbs) {
         final String pattern = AsyncAppenderAdminMBean.PATTERN;
         final String search = String.format(pattern, contextName, "*");
         unregisterAllMatching(search, mbs);
     }
 
-    private static void unregisterAsyncLoggerRingBufferAdmins(final String contextName,
-            final MBeanServer mbs) {
+    private static void unregisterAsyncLoggerRingBufferAdmins(final String contextName, final
MBeanServer mbs) {
         final String pattern1 = RingBufferAdminMBean.PATTERN_ASYNC_LOGGER;
         final String search1 = String.format(pattern1, contextName);
         unregisterAllMatching(search1, mbs);
     }
 
-    private static void unregisterAsyncLoggerConfigRingBufferAdmins(final String contextName,
-            final MBeanServer mbs) {
+    private static void unregisterAsyncLoggerConfigRingBufferAdmins(final String contextName,
final MBeanServer mbs) {
         final String pattern2 = RingBufferAdminMBean.PATTERN_ASYNC_LOGGER_CONFIG;
         final String search2 = String.format(pattern2, contextName, "*");
         unregisterAllMatching(search2, mbs);
@@ -347,7 +364,7 @@ public final class Server {
             final LoggerConfig cfg = map.get(name);
             final LoggerConfigAdmin mbean = new LoggerConfigAdmin(ctx.getName(), cfg);
             register(mbs, mbean, mbean.getObjectName());
-            
+
             if (cfg instanceof AsyncLoggerConfig) {
                 AsyncLoggerConfig async = (AsyncLoggerConfig) cfg;
                 RingBufferAdmin rbmbean = async.createRingBufferAdmin(ctx.getName());
@@ -362,7 +379,7 @@ public final class Server {
         final Map<String, Appender> map = ctx.getConfiguration().getAppenders();
         for (final String name : map.keySet()) {
             final Appender appender = map.get(name);
-            
+
             if (appender instanceof AsyncAppender) {
                 AsyncAppender async = ((AsyncAppender) appender);
                 final AsyncAppenderAdmin mbean = new AsyncAppenderAdmin(ctx.getName(), async);
@@ -373,8 +390,8 @@ public final class Server {
             }
         }
     }
-    
-    private static void register(MBeanServer mbs, Object mbean, ObjectName objectName) 
+
+    private static void register(MBeanServer mbs, Object mbean, ObjectName objectName)
             throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException
{
         LOGGER.debug("Registering MBean {}", objectName);
         mbs.registerMBean(mbean, objectName);

Modified: logging/log4j/log4j2/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/changes/changes.xml?rev=1557654&r1=1557653&r2=1557654&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/changes/changes.xml (original)
+++ logging/log4j/log4j2/trunk/src/changes/changes.xml Mon Jan 13 07:36:48 2014
@@ -21,6 +21,10 @@
   </properties>
   <body>
     <release version="2.0-RC1" date="2013-MM-DD" description="Bug fixes and enhancements">
+      <action issue="LOG4J2-406" dev="rpopma" type="fix" due-to="Kerrigan Joseph">
+        Unregister all log4j JMX MBeans when the LoggerContext is stopped
+        to allow web application classes to be GC-ed on undeploy.
+      </action>
       <action issue="LOG4J2-405" dev="rgoers" type="fix">
         Configuration was being processed twice at startup.
       </action>



Mime
View raw message