diff --git a/integration/pom.xml b/integration/pom.xml index b5e2ef7f..baff4296 100644 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -6,7 +6,7 @@ org.slf4j slf4j-parent - 1.5.10 + 1.5.11 4.0.0 diff --git a/jcl-over-slf4j/pom.xml b/jcl-over-slf4j/pom.xml index cac58f71..0d67bbb2 100644 --- a/jcl-over-slf4j/pom.xml +++ b/jcl-over-slf4j/pom.xml @@ -3,7 +3,7 @@ org.slf4j slf4j-parent - 1.5.10 + 1.5.11 4.0.0 diff --git a/jcl104-over-slf4j/pom.xml b/jcl104-over-slf4j/pom.xml index 5ce0a748..f8f8d4ef 100644 --- a/jcl104-over-slf4j/pom.xml +++ b/jcl104-over-slf4j/pom.xml @@ -3,7 +3,7 @@ org.slf4j slf4j-parent - 1.5.10 + 1.5.11 4.0.0 diff --git a/jul-to-slf4j/pom.xml b/jul-to-slf4j/pom.xml index 2bf3d278..a5b759bd 100644 --- a/jul-to-slf4j/pom.xml +++ b/jul-to-slf4j/pom.xml @@ -6,7 +6,7 @@ org.slf4j slf4j-parent - 1.5.10 + 1.5.11 4.0.0 diff --git a/log4j-over-slf4j/pom.xml b/log4j-over-slf4j/pom.xml index 9cd2586b..2f6d2d30 100644 --- a/log4j-over-slf4j/pom.xml +++ b/log4j-over-slf4j/pom.xml @@ -5,7 +5,7 @@ org.slf4j slf4j-parent - 1.5.10 + 1.5.11 4.0.0 diff --git a/log4j-over-slf4j/src/main/java/org/apache/log4j/Category.java b/log4j-over-slf4j/src/main/java/org/apache/log4j/Category.java index 279111e0..0d5d7659 100644 --- a/log4j-over-slf4j/src/main/java/org/apache/log4j/Category.java +++ b/log4j-over-slf4j/src/main/java/org/apache/log4j/Category.java @@ -45,6 +45,8 @@ public class Category { protected org.slf4j.Logger slf4jLogger; private org.slf4j.spi.LocationAwareLogger locationAwareLogger; + + private static Marker FATAL_MARKER = MarkerFactory.getMarker("FATAL"); Category(String name) { diff --git a/log4j-over-slf4j/src/main/java/org/apache/log4j/Log4jLoggerFactory.java b/log4j-over-slf4j/src/main/java/org/apache/log4j/Log4jLoggerFactory.java index fb3a70e3..d8d0ad74 100644 --- a/log4j-over-slf4j/src/main/java/org/apache/log4j/Log4jLoggerFactory.java +++ b/log4j-over-slf4j/src/main/java/org/apache/log4j/Log4jLoggerFactory.java @@ -18,6 +18,8 @@ package org.apache.log4j; import java.util.Hashtable; +import org.slf4j.helpers.Util; + /** * This class is a factory that creates and maintains org.apache.log4j.Loggers * wrapping org.slf4j.Loggers. @@ -32,12 +34,30 @@ class Log4jLoggerFactory { // String, Logger private static Hashtable log4jLoggers = new Hashtable(); + private static final String LOG4J_DELEGATION_LOOP_URL = "http://www.slf4j.org/codes.html#log4jDelegationLoop"; + + // check for delegation loops + static { + try { + Class.forName("org.slf4j.impl.Log4jLoggerFactory"); + String part1 = "Detected both log4j-over-slf4j.jar AND slf4j-log4j12.jar on the class path, preempting StackOverflowError. "; + String part2 = "See also " + LOG4J_DELEGATION_LOOP_URL + + " for more details."; + + Util.reportFailure(part1); + Util.reportFailure(part2); + throw new IllegalStateException(part1 + part2); + } catch (ClassNotFoundException e) { + // this is the good case + } + } + public static synchronized Logger getLogger(String name) { if (log4jLoggers.containsKey(name)) { return (org.apache.log4j.Logger) log4jLoggers.get(name); } else { Logger log4jLogger = new Logger(name); - + log4jLoggers.put(name, log4jLogger); return log4jLogger; } diff --git a/osgi-over-slf4j/pom.xml b/osgi-over-slf4j/pom.xml index ff817487..84197bac 100644 --- a/osgi-over-slf4j/pom.xml +++ b/osgi-over-slf4j/pom.xml @@ -3,7 +3,7 @@ org.slf4j slf4j-parent - 1.5.10 + 1.5.11 4.0.0 diff --git a/pom.xml b/pom.xml index b0514fb6..192f5e81 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.slf4j slf4j-parent - 1.5.10 + 1.5.11 pom SLF4J diff --git a/slf4j-api/pom.xml b/slf4j-api/pom.xml index e93733d7..c2726500 100644 --- a/slf4j-api/pom.xml +++ b/slf4j-api/pom.xml @@ -5,7 +5,7 @@ org.slf4j slf4j-parent - 1.5.10 + 1.5.11 4.0.0 diff --git a/slf4j-api/src/main/java/org/slf4j/LoggerFactory.java b/slf4j-api/src/main/java/org/slf4j/LoggerFactory.java index 6dd10e49..068d3dfd 100644 --- a/slf4j-api/src/main/java/org/slf4j/LoggerFactory.java +++ b/slf4j-api/src/main/java/org/slf4j/LoggerFactory.java @@ -85,7 +85,7 @@ public final class LoggerFactory { * compatibility. Thus, 1.5.7-SNAPSHOT, 1.5.7.RC0 are compatible with 1.5.7. */ static private final String[] API_COMPATIBILITY_LIST = new String[] { - "1.5.5", "1.5.6", "1.5.7", "1.5.8", "1.5.9", "1.5.10" }; + "1.5.5", "1.5.6", "1.5.7", "1.5.8", "1.5.9", "1.5.10", "1.5.11" }; // private constructor prevents instantiation private LoggerFactory() { diff --git a/slf4j-api/src/main/java/org/slf4j/impl/StaticLoggerBinder.java b/slf4j-api/src/main/java/org/slf4j/impl/StaticLoggerBinder.java index 89b97daf..169b7475 100644 --- a/slf4j-api/src/main/java/org/slf4j/impl/StaticLoggerBinder.java +++ b/slf4j-api/src/main/java/org/slf4j/impl/StaticLoggerBinder.java @@ -61,7 +61,7 @@ public class StaticLoggerBinder { * The value of this field is usually modified with each release. */ // to avoid constant folding by the compiler, this field must *not* be final - public static String REQUESTED_API_VERSION = "1.5.10"; // !final + public static String REQUESTED_API_VERSION = "1.5.11"; // !final private StaticLoggerBinder() { throw new UnsupportedOperationException("This code should have never made it into the jar"); diff --git a/slf4j-ext/pom.xml b/slf4j-ext/pom.xml index 636f9b09..8c16a118 100644 --- a/slf4j-ext/pom.xml +++ b/slf4j-ext/pom.xml @@ -5,7 +5,7 @@ org.slf4j slf4j-parent - 1.5.10 + 1.5.11 4.0.0 diff --git a/slf4j-jcl/pom.xml b/slf4j-jcl/pom.xml index edaaa0a6..088560b6 100644 --- a/slf4j-jcl/pom.xml +++ b/slf4j-jcl/pom.xml @@ -3,7 +3,7 @@ org.slf4j slf4j-parent - 1.5.10 + 1.5.11 4.0.0 diff --git a/slf4j-jcl/src/main/java/org/slf4j/impl/JCLLoggerFactory.java b/slf4j-jcl/src/main/java/org/slf4j/impl/JCLLoggerFactory.java index fddaf91a..c3ce6643 100644 --- a/slf4j-jcl/src/main/java/org/slf4j/impl/JCLLoggerFactory.java +++ b/slf4j-jcl/src/main/java/org/slf4j/impl/JCLLoggerFactory.java @@ -39,6 +39,7 @@ import java.util.Map; import org.apache.commons.logging.LogFactory; import org.slf4j.ILoggerFactory; import org.slf4j.Logger; +import org.slf4j.helpers.Util; /** * JCLLoggerFactory is an implementation of {@link ILoggerFactory} returning the @@ -48,6 +49,24 @@ import org.slf4j.Logger; */ public class JCLLoggerFactory implements ILoggerFactory { + private static final String JCL_DELEGATION_LOOP_URL = "http://www.slf4j.org/codes.html#jclDelegationLoop"; + + // check for delegation loops + static { + try { + Class.forName("org.apache.commons.logging.impl.SLF4JLogFactory"); + String part1 = "Detected both jcl-over-slf4j.jar AND slf4j-jcl.jar on the class path, preempting StackOverflowError. "; + String part2 = "See also " + JCL_DELEGATION_LOOP_URL + + " for more details."; + + Util.reportFailure(part1); + Util.reportFailure(part2); + throw new IllegalStateException(part1 + part2); + } catch (ClassNotFoundException e) { + // this is the good case + } + } + // key: name (String), value: a JCLLoggerAdapter; Map loggerMap; diff --git a/slf4j-jcl/src/main/java/org/slf4j/impl/StaticLoggerBinder.java b/slf4j-jcl/src/main/java/org/slf4j/impl/StaticLoggerBinder.java index 2b2514ae..9fea2be0 100644 --- a/slf4j-jcl/src/main/java/org/slf4j/impl/StaticLoggerBinder.java +++ b/slf4j-jcl/src/main/java/org/slf4j/impl/StaticLoggerBinder.java @@ -65,7 +65,7 @@ public class StaticLoggerBinder implements LoggerFactoryBinder { */ //to avoid constant folding by the compiler, this field must *not* be final - public static String REQUESTED_API_VERSION = "1.5.10"; + public static String REQUESTED_API_VERSION = "1.5.11"; // Binding specific code: private static final String loggerFactoryClassStr = JCLLoggerFactory.class diff --git a/slf4j-jdk14/pom.xml b/slf4j-jdk14/pom.xml index 8ca8ef6b..1cc86d16 100644 --- a/slf4j-jdk14/pom.xml +++ b/slf4j-jdk14/pom.xml @@ -6,7 +6,7 @@ org.slf4j slf4j-parent - 1.5.10 + 1.5.11 4.0.0 diff --git a/slf4j-jdk14/src/main/java/org/slf4j/impl/StaticLoggerBinder.java b/slf4j-jdk14/src/main/java/org/slf4j/impl/StaticLoggerBinder.java index c4d2073e..92e9db8d 100644 --- a/slf4j-jdk14/src/main/java/org/slf4j/impl/StaticLoggerBinder.java +++ b/slf4j-jdk14/src/main/java/org/slf4j/impl/StaticLoggerBinder.java @@ -66,7 +66,7 @@ public class StaticLoggerBinder implements LoggerFactoryBinder { * The value of this field is usually modified with each release. */ // to avoid constant folding by the compiler, this field must *not* be final - public static String REQUESTED_API_VERSION = "1.5.10"; // !final + public static String REQUESTED_API_VERSION = "1.5.11"; // !final private static final String loggerFactoryClassStr = org.slf4j.impl.JDK14LoggerFactory.class.getName(); diff --git a/slf4j-log4j12/pom.xml b/slf4j-log4j12/pom.xml index e8a65485..070e32f9 100644 --- a/slf4j-log4j12/pom.xml +++ b/slf4j-log4j12/pom.xml @@ -6,7 +6,7 @@ org.slf4j slf4j-parent - 1.5.10 + 1.5.11 4.0.0 diff --git a/slf4j-log4j12/src/main/java/org/slf4j/impl/StaticLoggerBinder.java b/slf4j-log4j12/src/main/java/org/slf4j/impl/StaticLoggerBinder.java index 6cf6d230..2e86c524 100644 --- a/slf4j-log4j12/src/main/java/org/slf4j/impl/StaticLoggerBinder.java +++ b/slf4j-log4j12/src/main/java/org/slf4j/impl/StaticLoggerBinder.java @@ -66,7 +66,7 @@ public class StaticLoggerBinder implements LoggerFactoryBinder { * against. The value of this field is usually modified with each release. */ // to avoid constant folding by the compiler, this field must *not* be final - public static String REQUESTED_API_VERSION = "1.5.10"; // !final + public static String REQUESTED_API_VERSION = "1.5.11"; // !final private static final String loggerFactoryClassStr = Log4jLoggerFactory.class .getName(); diff --git a/slf4j-migrator/pom.xml b/slf4j-migrator/pom.xml index 69392d03..768a9b05 100644 --- a/slf4j-migrator/pom.xml +++ b/slf4j-migrator/pom.xml @@ -7,7 +7,7 @@ org.slf4j slf4j-parent - 1.5.10 + 1.5.11 4.0.0 diff --git a/slf4j-nop/pom.xml b/slf4j-nop/pom.xml index fed1241c..01f77811 100644 --- a/slf4j-nop/pom.xml +++ b/slf4j-nop/pom.xml @@ -6,7 +6,7 @@ org.slf4j slf4j-parent - 1.5.10 + 1.5.11 4.0.0 diff --git a/slf4j-nop/src/main/java/org/slf4j/impl/StaticLoggerBinder.java b/slf4j-nop/src/main/java/org/slf4j/impl/StaticLoggerBinder.java index 109e4152..4c147923 100644 --- a/slf4j-nop/src/main/java/org/slf4j/impl/StaticLoggerBinder.java +++ b/slf4j-nop/src/main/java/org/slf4j/impl/StaticLoggerBinder.java @@ -66,7 +66,7 @@ public class StaticLoggerBinder implements LoggerFactoryBinder { * The value of this field is usually modified with each release. */ // to avoid constant folding by the compiler, this field must *not* be final - public static String REQUESTED_API_VERSION = "1.5.10"; // !final + public static String REQUESTED_API_VERSION = "1.5.11"; // !final private static final String loggerFactoryClassStr = NOPLoggerFactory.class.getName(); diff --git a/slf4j-osgi-integration-test/pom.xml b/slf4j-osgi-integration-test/pom.xml index 8ea99dc7..8951a134 100644 --- a/slf4j-osgi-integration-test/pom.xml +++ b/slf4j-osgi-integration-test/pom.xml @@ -6,7 +6,7 @@ org.slf4j slf4j-parent - 1.5.10 + 1.5.11 4.0.0 diff --git a/slf4j-osgi-test-bundle/pom.xml b/slf4j-osgi-test-bundle/pom.xml index 723382ee..97c09a23 100644 --- a/slf4j-osgi-test-bundle/pom.xml +++ b/slf4j-osgi-test-bundle/pom.xml @@ -6,7 +6,7 @@ org.slf4j slf4j-parent - 1.5.10 + 1.5.11 4.0.0 diff --git a/slf4j-simple/pom.xml b/slf4j-simple/pom.xml index cb5c89c0..f582310b 100644 --- a/slf4j-simple/pom.xml +++ b/slf4j-simple/pom.xml @@ -3,7 +3,7 @@ org.slf4j slf4j-parent - 1.5.10 + 1.5.11 4.0.0 diff --git a/slf4j-simple/src/main/java/org/slf4j/impl/StaticLoggerBinder.java b/slf4j-simple/src/main/java/org/slf4j/impl/StaticLoggerBinder.java index 5bc87a45..064cb9ee 100644 --- a/slf4j-simple/src/main/java/org/slf4j/impl/StaticLoggerBinder.java +++ b/slf4j-simple/src/main/java/org/slf4j/impl/StaticLoggerBinder.java @@ -58,7 +58,7 @@ public class StaticLoggerBinder implements LoggerFactoryBinder { * against. The value of this field is usually modified with each release. */ // to avoid constant folding by the compiler, this field must *not* be final - public static String REQUESTED_API_VERSION = "1.5.10"; // !final + public static String REQUESTED_API_VERSION = "1.5.11"; // !final private static final String loggerFactoryClassStr = SimpleLoggerFactory.class.getName(); diff --git a/slf4j-site/pom.xml b/slf4j-site/pom.xml index c17dacdc..68116ff6 100644 --- a/slf4j-site/pom.xml +++ b/slf4j-site/pom.xml @@ -5,7 +5,7 @@ org.slf4j slf4j-parent - 1.5.10 + 1.5.11 4.0.0 diff --git a/slf4j-site/src/site/pages/codes.html b/slf4j-site/src/site/pages/codes.html index 2c72e029..f5d7ed2e 100644 --- a/slf4j-site/src/site/pages/codes.html +++ b/slf4j-site/src/site/pages/codes.html @@ -1,11 +1,13 @@ - -SLF4J Error Codes - + + SLF4J Error Codes + + - + + @@ -13,6 +15,7 @@ +
@@ -151,7 +154,7 @@ slf4j-simple-${version}.jar and slf4j-nop-${version}.jar on the class path and you wish to use the nop (no-operation) binding, then remove - slf4j-simple-${version}.jar from the class parh.

+ slf4j-simple-${version}.jar from the class path.

@@ -168,7 +171,102 @@ an effective remedy.

- + + +

+ Detected both log4j-over-slf4j.jar + AND slf4j-log4j12.jar on the class path, preempting + StackOverflowError. +

+ +

The purpose of slf4j-log4j12 module is to delegate or redirect + calls made to an SLF4J logger to log4j. The purpose of the + log4j-over-slf4j module is to redirect calls made to a log4j + logger to SLF4J. If both slf4j-log4j12.jar and + log4j-over-slf4j.jar are present on the class path, a + StackOverflowError will inevitably occur immediately + after the first invocation of an SLF4J or a log4j logger. +

+ +

Here is how the exception might look like:

+ +
Exception in thread "main" java.lang.StackOverflowError
+  at java.util.Hashtable.containsKey(Hashtable.java:306)
+  at org.apache.log4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:36)
+  at org.apache.log4j.LogManager.getLogger(LogManager.java:39)
+  at org.slf4j.impl.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:73)
+  at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:249)
+  at org.apache.log4j.Category.<init>(Category.java:53)
+  at org.apache.log4j.Logger..<init>(Logger.java:35)
+  at org.apache.log4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:39)
+  at org.apache.log4j.LogManager.getLogger(LogManager.java:39)
+  at org.slf4j.impl.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:73)
+  at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:249)
+  at org.apache.log4j.Category..<init>(Category.java:53)
+  at org.apache.log4j.Logger..<init>(Logger.java:35)
+  at org.apache.log4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:39)
+  at org.apache.log4j.LogManager.getLogger(LogManager.java:39)
+  subsequent lines omitted...
+ +

As of SLF4J version 1.5.11, the code preempts the inevitable + stack overflow error by throwing an exception with details about + the actual cause of the problem. This is deemed to be better than + leaving the user wondering about the reasons of the + StackOverflowError. +

+ +

For more background on this topic see Bridging legacy APIs. +

+ + + + +

+ Detected + both jcl-over-slf4j.jar AND slf4j-jcl.jar on the class path, + preempting StackOverflowError. +

+ +

The purpose of slf4j-jcl module is to delegate or redirect + calls made to an SLF4J logger to jakarta commons logging + (JCL). The purpose of the jcl-over-slf4j module is to redirect + calls made to a JCL logger to SLF4J. If both + slf4j-jcl.jar and jcl-over-slf4j.jar are present + on the class path, then a StackOverflowError will + inevitably occur immediately after the first invocation of an + SLF4J or a JCL logger. +

+ +

Here is how the exception might look like:

+ +
Exception in thread "main" java.lang.StackOverflowError
+  at java.lang.String.hashCode(String.java:1482)
+  at java.util.HashMap.get(HashMap.java:300)
+  at org.slf4j.impl.JCLLoggerFactory.getLogger(JCLLoggerFactory.java:67)
+  at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:249)
+  at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:155)
+  at org.apache.commons.logging.LogFactory.getLog(LogFactory.java:289)
+  at org.slf4j.impl.JCLLoggerFactory.getLogger(JCLLoggerFactory.java:69)
+  at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:249)
+  at org.apache.commons.logging.impl.SLF4JLogFactory.getInstance(SLF4JLogFactory.java:155)
+  subsequent lines omitted...
+ + +

As of SLF4J version 1.5.11, the code preempts the inevitable + stack overflow error by throwing an exception with details about + the actual cause of the problem. This is deemed to be better than + leaving the user wondering about the reasons of the + StackOverflowError. +

+ +

For more background on this topic see Bridging legacy APIs. +

+ + +

Failed to load class diff --git a/slf4j-site/src/site/pages/legacy.html b/slf4j-site/src/site/pages/legacy.html index a5ba3768..fa8d54da 100644 --- a/slf4j-site/src/site/pages/legacy.html +++ b/slf4j-site/src/site/pages/legacy.html @@ -101,10 +101,10 @@

Please note that jcl-over-slf4j.jar and slf4j-jcl.jar cannot be deployed at the same time. The - former jar file will cause JCL to delegate the choice of the logging - system to SLF4J and the latter jar file will cause SLF4J to delegate - the choice of the logging system to JCL, resulting in an infinite - loop. + former jar file will cause JCL to delegate the choice of the + logging system to SLF4J and the latter jar file will cause SLF4J + to delegate the choice of the logging system to JCL, resulting in + an infinite loop.

@@ -184,9 +184,10 @@

The presence of slf4j-logj12.jar, that is the log4j binding for SLF4J, will force all SLF4J calls to be delegated to log4j. The presence of log4j-over-slf4j.jar will in turn - delegate all log4j API calls to their SLF4J equivalents. If both are - present simultaneously, slf4j calls will be delegated to log4j, and - log4j calls redirected to SLF4j, resulting in an endless loop. + delegate all log4j API calls to their SLF4J equivalents. If both + are present simultaneously, slf4j calls will be delegated to + log4j, and log4j calls redirected to SLF4j, resulting in an endless loop.

JUL to SLF4J

diff --git a/slf4j-site/src/site/pages/news.html b/slf4j-site/src/site/pages/news.html index 8b043278..b5a8c710 100644 --- a/slf4j-site/src/site/pages/news.html +++ b/slf4j-site/src/site/pages/news.html @@ -27,7 +27,20 @@
-

March xx, 2010 - Release of SLF4J 1.5.11

+

February 25th, 2010 - Release of SLF4J 1.5.11

+ + +

Users yet unfamiliar with SLF4J sometimes unknowingly place both + log4j-over-slf4j.jar and slf4j-log4j12.jar + simultanously on the class path causing stack overflow + errors. Simultaneously placing both jcl-over-slf4j.jar and + slf4j-jcl.jar on the class path, is another occurrence of + the same general problem. As of this version, SLF4J preempts the + inevitable stack overflow error by throwing an exception with + details about the actual cause of the problem. This is deemed to be + better than leaving the user wondering about the reasons of the + StackOverflowError. +

Fixed bug 168. In case log4j-over-slf4j is used and a logback appender