You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-dev@logging.apache.org by ca...@apache.org on 2008/08/08 05:00:16 UTC

svn commit: r683811 - in /logging/log4j/trunk/src: changes/changes.xml main/java/org/apache/log4j/LogManager.java site/fml/faq.fml

Author: carnold
Date: Thu Aug  7 20:00:16 2008
New Revision: 683811

URL: http://svn.apache.org/viewvc?rev=683811&view=rev
Log:
Bug 43867: Improve error when Logger.getLogger is called after unloading

Modified:
    logging/log4j/trunk/src/changes/changes.xml
    logging/log4j/trunk/src/main/java/org/apache/log4j/LogManager.java
    logging/log4j/trunk/src/site/fml/faq.fml

Modified: logging/log4j/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/logging/log4j/trunk/src/changes/changes.xml?rev=683811&r1=683810&r2=683811&view=diff
==============================================================================
--- logging/log4j/trunk/src/changes/changes.xml (original)
+++ logging/log4j/trunk/src/changes/changes.xml Thu Aug  7 20:00:16 2008
@@ -44,6 +44,7 @@
        <action action="fix" issue="44517">Eliminate compile dependency on non-redistributable JMS reference implementation.</action> 
        <action action="fix" issue="37182">Exception in call to toString of message propagates to caller.</action>
        <action action="fix" issue="45299">Javadoc class index corrupted by JDBCAppender deprecation warning.</action> 
+       <action action="fix" issue="43867">Improve warning message when log4j is accessed after unload by Tomcat.</action>
     </release>
   
     <release version="1.2.15" date="2007-08-24" description="SyslogAppender enhancements, NTEventLogAppender and Maven build.">

Modified: logging/log4j/trunk/src/main/java/org/apache/log4j/LogManager.java
URL: http://svn.apache.org/viewvc/logging/log4j/trunk/src/main/java/org/apache/log4j/LogManager.java?rev=683811&r1=683810&r2=683811&view=diff
==============================================================================
--- logging/log4j/trunk/src/main/java/org/apache/log4j/LogManager.java (original)
+++ logging/log4j/trunk/src/main/java/org/apache/log4j/LogManager.java Thu Aug  7 20:00:16 2008
@@ -32,6 +32,8 @@
 
 
 import java.util.Enumeration;
+import java.io.StringWriter;
+import java.io.PrintWriter;
 
 /**
  * Use the <code>LogManager</code> class to retreive {@link Logger}
@@ -168,13 +170,37 @@
     LogManager.repositorySelector = selector;
   }
 
+
+    /**
+     * This method tests if called from a method that
+     * is known to result in class members being abnormally
+     * set to null but is assumed to be harmless since the
+     * all classes are in the process of being unloaded.
+     *
+     * @param ex exception used to determine calling stack.
+     * @return true if calling stack is recognized as likely safe.
+     */
+  private static boolean isLikelySafeScenario(final Exception ex) {
+      StringWriter stringWriter = new StringWriter();
+      ex.printStackTrace(new PrintWriter(stringWriter));
+      String msg = stringWriter.toString();
+      return msg.indexOf("org.apache.catalina.loader.WebappClassLoader.stop") != -1;
+  }
+
   static
   public
   LoggerRepository getLoggerRepository() {
     if (repositorySelector == null) {
         repositorySelector = new DefaultRepositorySelector(new NOPLoggerRepository());
         guard = null;
-        LogLog.error("LogMananger.repositorySelector was null likely due to error in class reloading, using NOPLoggerRepository.");
+        Exception ex = new IllegalStateException("Class invariant violation");
+        String msg =
+                "log4j called after unloading, see http://logging.apache.org/log4j/1.2/faq.html#unload.";
+        if (isLikelySafeScenario(ex)) {
+            LogLog.debug(msg, ex);
+        } else {
+            LogLog.error(msg, ex);
+        }
     }
     return repositorySelector.getLoggerRepository();
   }

Modified: logging/log4j/trunk/src/site/fml/faq.fml
URL: http://svn.apache.org/viewvc/logging/log4j/trunk/src/site/fml/faq.fml?rev=683811&r1=683810&r2=683811&view=diff
==============================================================================
--- logging/log4j/trunk/src/site/fml/faq.fml (original)
+++ logging/log4j/trunk/src/site/fml/faq.fml Thu Aug  7 20:00:16 2008
@@ -777,5 +777,51 @@
           logger name (or tree) for "audit" related messages.</p>
         </answer>
       </faq>
+
+      <faq id="unload">
+          <question>Why does log4j throw a NullPointerException or
+              print a message about NOPLoggerRepository
+              when shutting down or restarting under Tomcat or during a shutdown
+              hook?</question>
+          <answer><p>Tomcat will, by default,
+             clear all static members when unloading classes.
+             Unfortunately, under certain circumstances
+             another class may attempt to call log4j after log4j
+             has had its private member variables cleared, resulting in either
+             a NullPointerException (log4j 1.2.14 or earlier) or a console
+             message (log4j 1.2.15 and later).  The same type of issue
+             has been reported during various shutdown hooks (see bug
+             <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=40212">40212</a>)
+             but the mechanisms are not as well understood.</p>
+
+             <p>The following have been recommended to avoid this problem:
+                 <ol>
+                     <li>Set the org.apache.catalina.loader.WebappClassLoader.ENABLE_CLEAR_REFERENCES
+                         system property to false.</li>
+                     <li>Upgrade to log4j 1.2.16 or later to better defend against class loader attack
+                         or provide a better diagnostic message when it does occur.</li>
+                     <li>Use per-application copies of log4j, that is remove log4j.jar from WEB-INF/lib.</li>
+                     <li>Avoid calls to log4j from within class initialization.</li>
+                     <li>Upgrade to the latest version of the framework that causing the problem.</li>
+                     <li>Use EnhancedPatternLayout from the extras companion when the NPE occurs
+                         in a call of PatternLayout.</li>
+                 </ol>
+             </p>
+
+            <p>It is impossible for log4j to defend against all attacks on
+                its internal state by a class loader.  There is a limit to
+                the defensive measures that will be incorporated.</p>
+
+             <p>For more background, see bugs
+              <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=40212">40212</a>,   
+              <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=41939">41939</a>,
+              <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=43867">43867</a>,
+              <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=40159">40159</a>,
+              <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=43181">43181</a>,
+              <a href="http://issues.apache.org/bugzilla/show_bug.cgi?id=41316">41316</a> and
+              <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=37956">37956</a>.
+             </p>
+          </answer>
+      </faq>
   </part>
 </faqs>



---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org