mirror of https://github.com/qos-ch/slf4j
Merge remote-tracking branch 'origin' into slf4j-344-logServiceReader
Conflicts: osgi-over-slf4j/pom.xml
This commit is contained in:
commit
9bea50f144
|
|
@ -17,7 +17,6 @@
|
|||
package org.apache.log4j;
|
||||
|
||||
import org.apache.log4j.spi.LoggerFactory;
|
||||
import org.slf4j.helpers.Util;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
|
@ -36,23 +35,6 @@ class Log4jLoggerFactory {
|
|||
// String, Logger
|
||||
private static ConcurrentMap<String, Logger> log4jLoggers = new ConcurrentHashMap<String, Logger>();
|
||||
|
||||
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.report(part1);
|
||||
Util.report(part2);
|
||||
throw new IllegalStateException(part1 + part2);
|
||||
} catch (ClassNotFoundException e) {
|
||||
// this is the good case
|
||||
}
|
||||
}
|
||||
|
||||
public static Logger getLogger(String name) {
|
||||
org.apache.log4j.Logger instance = log4jLoggers.get(name);
|
||||
if (instance != null) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
Implementation-Title: osgi-over-slf4j
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-SymbolicName: org.slf4j.osgi-over-slf4j
|
||||
Bundle-Name: OSGi LogService implemented over SLF4J
|
||||
Bundle-RequiredExecutionEnvironment: J2SE-1.5
|
||||
Bundle-Activator: org.slf4j.osgi.logservice.impl.Activator
|
||||
Bundle-Category: osgi
|
||||
Import-Package: org.osgi.framework;version="[1.5,2)",org.osgi.service.log;version="[1.3,2)",org.slf4j;version=${parsedVersion.osgiVersion}
|
||||
|
|
@ -44,6 +44,15 @@ public class StaticMDCBinder {
|
|||
private StaticMDCBinder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the singleton of this class.
|
||||
*
|
||||
* @return the StaticMDCBinder singleton
|
||||
* @since 1.7.14
|
||||
*/
|
||||
public static final StaticMDCBinder getSingleton() {
|
||||
return SINGLETON;
|
||||
}
|
||||
/**
|
||||
* Currently this method always returns an instance of
|
||||
* {@link NOPMDCAdapter}.
|
||||
|
|
|
|||
|
|
@ -49,6 +49,16 @@ public class StaticMarkerBinder implements MarkerFactoryBinder {
|
|||
private StaticMarkerBinder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the singleton of this class.
|
||||
*
|
||||
* @return the StaticMarkerBinder singleton
|
||||
* @since 1.7.14
|
||||
*/
|
||||
public static StaticMarkerBinder getSingleton() {
|
||||
return SINGLETON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently this method always returns an instance of
|
||||
* {@link BasicMarkerFactory}.
|
||||
|
|
|
|||
|
|
@ -84,6 +84,8 @@ public final class LoggerFactory {
|
|||
|
||||
// Support for detecting mismatched logger names.
|
||||
static final String DETECT_LOGGER_NAME_MISMATCH_PROPERTY = "slf4j.detectLoggerNameMismatch";
|
||||
static final String JAVA_VENDOR_PROPERTY = "java.vendor.url";
|
||||
|
||||
static boolean DETECT_LOGGER_NAME_MISMATCH = Util.safeGetBooleanSystemProperty(DETECT_LOGGER_NAME_MISMATCH_PROPERTY);
|
||||
|
||||
/**
|
||||
|
|
@ -254,6 +256,11 @@ public final class LoggerFactory {
|
|||
*
|
||||
*/
|
||||
private static void reportMultipleBindingAmbiguity(Set<URL> staticLoggerBinderPathSet) {
|
||||
if(isAndroid()) {
|
||||
// skip check under android, see also http://jira.qos.ch/browse/SLF4J-328
|
||||
return;
|
||||
}
|
||||
|
||||
if (isAmbiguousStaticLoggerBinderPathSet(staticLoggerBinderPathSet)) {
|
||||
Util.report("Class path contains multiple SLF4J bindings.");
|
||||
for (URL path : staticLoggerBinderPathSet) {
|
||||
|
|
@ -263,6 +270,13 @@ public final class LoggerFactory {
|
|||
}
|
||||
}
|
||||
|
||||
private static boolean isAndroid() {
|
||||
String vendor = Util.safeGetSystemProperty(JAVA_VENDOR_PROPERTY);
|
||||
if(vendor == null)
|
||||
return false;
|
||||
return vendor.toLowerCase().contains("android");
|
||||
}
|
||||
|
||||
private static void reportActualBinding(Set<URL> staticLoggerBinderPathSet) {
|
||||
if (isAmbiguousStaticLoggerBinderPathSet(staticLoggerBinderPathSet)) {
|
||||
Util.report("Actual binding is of type [" + StaticLoggerBinder.getSingleton().getLoggerFactoryClassStr() + "]");
|
||||
|
|
|
|||
|
|
@ -85,9 +85,27 @@ public class MDC {
|
|||
private MDC() {
|
||||
}
|
||||
|
||||
/**
|
||||
* As of SLF4J version 1.7.14, StaticMDCBinder classes shipping in various bindings
|
||||
* come with a getSingleton() method. Previously only a public field called SINGLETON
|
||||
* was available.
|
||||
*
|
||||
* @return MDCAdapter
|
||||
* @throws NoClassDefFoundError in case no binding is available
|
||||
* @since 1.7.14
|
||||
*/
|
||||
private static MDCAdapter bwCompatibleGetMDCAdapterFromBinder() throws NoClassDefFoundError {
|
||||
try {
|
||||
return StaticMDCBinder.getSingleton().getMDCA();
|
||||
} catch (NoSuchMethodError nsme) {
|
||||
// binding is probably a version of SLF4J older than 1.7.14
|
||||
return StaticMDCBinder.SINGLETON.getMDCA();
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
mdcAdapter = StaticMDCBinder.SINGLETON.getMDCA();
|
||||
mdcAdapter = bwCompatibleGetMDCAdapterFromBinder();
|
||||
} catch (NoClassDefFoundError ncde) {
|
||||
mdcAdapter = new NOPMDCAdapter();
|
||||
String msg = ncde.getMessage();
|
||||
|
|
|
|||
|
|
@ -42,17 +42,35 @@ import org.slf4j.impl.StaticMarkerBinder;
|
|||
* @author Ceki Gülcü
|
||||
*/
|
||||
public class MarkerFactory {
|
||||
static IMarkerFactory markerFactory;
|
||||
static IMarkerFactory MARKER_FACTORY;
|
||||
|
||||
private MarkerFactory() {
|
||||
}
|
||||
|
||||
/**
|
||||
* As of SLF4J version 1.7.14, StaticMarkerBinder classes shipping in various bindings
|
||||
* come with a getSingleton() method. Previously only a public field called SINGLETON
|
||||
* was available.
|
||||
*
|
||||
* @return IMarkerFactory
|
||||
* @throws NoClassDefFoundError in case no binding is available
|
||||
* @since 1.7.14
|
||||
*/
|
||||
private static IMarkerFactory bwCompatibleGetMarkerFactoryFromBinder() throws NoClassDefFoundError {
|
||||
try {
|
||||
return StaticMarkerBinder.getSingleton().getMarkerFactory();
|
||||
} catch (NoSuchMethodError nsme) {
|
||||
// binding is probably a version of SLF4J older than 1.7.14
|
||||
return StaticMarkerBinder.SINGLETON.getMarkerFactory();
|
||||
}
|
||||
}
|
||||
|
||||
// this is where the binding happens
|
||||
static {
|
||||
try {
|
||||
markerFactory = StaticMarkerBinder.SINGLETON.getMarkerFactory();
|
||||
MARKER_FACTORY = bwCompatibleGetMarkerFactoryFromBinder();
|
||||
} catch (NoClassDefFoundError e) {
|
||||
markerFactory = new BasicMarkerFactory();
|
||||
|
||||
MARKER_FACTORY = new BasicMarkerFactory();
|
||||
} catch (Exception e) {
|
||||
// we should never get here
|
||||
Util.report("Unexpected failure while binding MarkerFactory", e);
|
||||
|
|
@ -68,7 +86,7 @@ public class MarkerFactory {
|
|||
* @return marker
|
||||
*/
|
||||
public static Marker getMarker(String name) {
|
||||
return markerFactory.getMarker(name);
|
||||
return MARKER_FACTORY.getMarker(name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -79,7 +97,7 @@ public class MarkerFactory {
|
|||
* @since 1.5.1
|
||||
*/
|
||||
public static Marker getDetachedMarker(String name) {
|
||||
return markerFactory.getDetachedMarker(name);
|
||||
return MARKER_FACTORY.getDetachedMarker(name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -91,6 +109,6 @@ public class MarkerFactory {
|
|||
* @return the IMarkerFactory instance in use
|
||||
*/
|
||||
public static IMarkerFactory getIMarkerFactory() {
|
||||
return markerFactory;
|
||||
return MARKER_FACTORY;
|
||||
}
|
||||
}
|
||||
|
|
@ -42,6 +42,16 @@ public class StaticMDCBinder {
|
|||
private StaticMDCBinder() {
|
||||
throw new UnsupportedOperationException("This code should never make it into the jar");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the singleton of this class.
|
||||
*
|
||||
* @return the StaticMDCBinder singleton
|
||||
* @since 1.7.14
|
||||
*/
|
||||
public static final StaticMDCBinder getSingleton() {
|
||||
return SINGLETON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently this method always returns an instance of
|
||||
|
|
|
|||
|
|
@ -51,6 +51,16 @@ public class StaticMarkerBinder implements MarkerFactoryBinder {
|
|||
throw new UnsupportedOperationException("This code should never make it into the jar");
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the singleton of this class.
|
||||
*
|
||||
* @return the StaticMarkerBinder singleton
|
||||
* @since 1.7.14
|
||||
*/
|
||||
public static StaticMarkerBinder getSingleton() {
|
||||
return SINGLETON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently this method always returns an instance of
|
||||
* {@link BasicMarkerFactory}.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,141 @@
|
|||
package org.slf4j;
|
||||
|
||||
import java.util.concurrent.BrokenBarrierException;
|
||||
import java.util.concurrent.CyclicBarrier;
|
||||
|
||||
/**
|
||||
* This class demonstrates that threads accessing the STATE variable always see a consistent value.
|
||||
*
|
||||
* During ongoing initialization the observed value is either ONGOING_INITIALIZATION
|
||||
* or one of {SUCCESS, FAILURE}.
|
||||
*
|
||||
* Post initialization the observed value is always one of {SUCCESS, FAILURE}.
|
||||
*
|
||||
* See also http://jira.qos.ch/browse/SLF4J-167
|
||||
*
|
||||
* @author ceki
|
||||
*
|
||||
*/
|
||||
public class DoubleCheckedInt {
|
||||
|
||||
final static int THREAD_COUNT = 10 + Runtime.getRuntime().availableProcessors() * 2;
|
||||
final static int UNINITIALIZED_STATE = 0;
|
||||
final static int ONGOING_INITIALIZATION = 1;
|
||||
final static int SUCCESS = 2;
|
||||
final static int FAILURE = 3;
|
||||
final static int NUMBER_OF_STATES = FAILURE + 1;
|
||||
|
||||
private static int STATE = UNINITIALIZED_STATE;
|
||||
|
||||
public static int getState() {
|
||||
if (STATE == 0) {
|
||||
synchronized (DoubleCheckedInt.class) {
|
||||
if (STATE == UNINITIALIZED_STATE) {
|
||||
STATE = ONGOING_INITIALIZATION;
|
||||
long r = System.nanoTime();
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
if (r % 2 == 0) {
|
||||
STATE = SUCCESS;
|
||||
} else {
|
||||
STATE = FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return STATE;
|
||||
}
|
||||
|
||||
static public void main(String[] args) throws InterruptedException, BrokenBarrierException {
|
||||
StateAccessingThread[] preInitializationThreads = harness();
|
||||
check(preInitializationThreads, false);
|
||||
|
||||
System.out.println("============");
|
||||
StateAccessingThread[] postInitializationThreads = harness();
|
||||
check(postInitializationThreads, true);
|
||||
}
|
||||
|
||||
private static StateAccessingThread[] harness() throws InterruptedException, BrokenBarrierException {
|
||||
StateAccessingThread[] threads = new StateAccessingThread[THREAD_COUNT];
|
||||
final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
|
||||
for (int i = 0; i < THREAD_COUNT; i++) {
|
||||
threads[i] = new StateAccessingThread(barrier);
|
||||
threads[i].start();
|
||||
}
|
||||
|
||||
barrier.await();
|
||||
for (int i = 0; i < THREAD_COUNT; i++) {
|
||||
threads[i].join();
|
||||
}
|
||||
return threads;
|
||||
}
|
||||
|
||||
private static void check(StateAccessingThread[] threads, boolean postInit) {
|
||||
|
||||
int[] stateCount = getStateCount(threads);
|
||||
printStateCount(stateCount);
|
||||
|
||||
if (stateCount[UNINITIALIZED_STATE] != 0) {
|
||||
throw new IllegalStateException("getState() should never return a zero value");
|
||||
}
|
||||
|
||||
if (stateCount[SUCCESS] != 0 && stateCount[FAILURE] != 0) {
|
||||
throw new IllegalStateException("getState() should return consistent values");
|
||||
}
|
||||
|
||||
if (postInit) {
|
||||
if (stateCount[SUCCESS] != THREAD_COUNT && stateCount[FAILURE] != THREAD_COUNT) {
|
||||
throw new IllegalStateException("getState() should return consistent values");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void printStateCount(int[] stateCount) {
|
||||
for (int i = 0; i < NUMBER_OF_STATES; i++) {
|
||||
switch (i) {
|
||||
case UNINITIALIZED_STATE:
|
||||
System.out.println("UNINITIALIZED_STATE count: " + stateCount[i]);
|
||||
break;
|
||||
case ONGOING_INITIALIZATION:
|
||||
System.out.println("ONGOING_INITIALIZATION count: " + stateCount[i]);
|
||||
break;
|
||||
case SUCCESS:
|
||||
System.out.println("SUCCESS count: " + stateCount[i]);
|
||||
break;
|
||||
case FAILURE:
|
||||
System.out.println("FAILURE count: " + stateCount[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int[] getStateCount(StateAccessingThread[] threads) {
|
||||
int[] valCount = new int[NUMBER_OF_STATES];
|
||||
for (int i = 0; i < threads.length; i++) {
|
||||
int val = threads[i].state;
|
||||
valCount[val] = valCount[val] + 1;
|
||||
}
|
||||
return valCount;
|
||||
}
|
||||
|
||||
static class StateAccessingThread extends Thread {
|
||||
public int state = -1;
|
||||
final CyclicBarrier barrier;
|
||||
|
||||
StateAccessingThread(CyclicBarrier barrier) {
|
||||
this.barrier = barrier;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
barrier.await();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
state = DoubleCheckedInt.getState();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -46,7 +46,7 @@ public class JCLLoggerFactory implements ILoggerFactory {
|
|||
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 part1 = "Detected both jcl-over-slf4j.jar AND bound slf4j-jcl.jar on the class path, preempting StackOverflowError. ";
|
||||
String part2 = "See also " + JCL_DELEGATION_LOOP_URL + " for more details.";
|
||||
|
||||
Util.report(part1);
|
||||
|
|
@ -58,7 +58,7 @@ public class JCLLoggerFactory implements ILoggerFactory {
|
|||
}
|
||||
|
||||
// key: name (String), value: a JCLLoggerAdapter;
|
||||
ConcurrentMap<String, Logger> loggerMap;
|
||||
final ConcurrentMap<String, Logger> loggerMap;
|
||||
|
||||
public JCLLoggerFactory() {
|
||||
loggerMap = new ConcurrentHashMap<String, Logger>();
|
||||
|
|
|
|||
|
|
@ -42,11 +42,22 @@ public class StaticMDCBinder {
|
|||
private StaticMDCBinder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the singleton of this class.
|
||||
*
|
||||
* @return the StaticMDCBinder singleton
|
||||
* @since 1.7.14
|
||||
*/
|
||||
public static final StaticMDCBinder getSingleton() {
|
||||
return SINGLETON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently this method always returns an instance of
|
||||
* {@link NOPMDCAdapter}.
|
||||
*
|
||||
* @return instance of NOPMDCAdapter
|
||||
* @since 1.7.14
|
||||
*/
|
||||
public MDCAdapter getMDCA() {
|
||||
return new NOPMDCAdapter();
|
||||
|
|
|
|||
|
|
@ -48,6 +48,16 @@ public class StaticMarkerBinder implements MarkerFactoryBinder {
|
|||
private StaticMarkerBinder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the singleton of this class.
|
||||
*
|
||||
* @return the StaticMarkerBinder singleton
|
||||
* @since 1.7.14
|
||||
*/
|
||||
public static StaticMarkerBinder getSingleton() {
|
||||
return SINGLETON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently this method always returns an instance of
|
||||
* {@link BasicMarkerFactory}.
|
||||
|
|
|
|||
|
|
@ -41,7 +41,17 @@ public class StaticMDCBinder {
|
|||
|
||||
private StaticMDCBinder() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the singleton of this class.
|
||||
*
|
||||
* @return the StaticMDCBinder singleton
|
||||
* @since 1.7.14
|
||||
*/
|
||||
public static final StaticMDCBinder getSingleton() {
|
||||
return SINGLETON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently this method always returns an instance of
|
||||
* {@link BasicMDCAdapter}.
|
||||
|
|
|
|||
|
|
@ -48,6 +48,16 @@ public class StaticMarkerBinder implements MarkerFactoryBinder {
|
|||
private StaticMarkerBinder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the singleton of this class.
|
||||
*
|
||||
* @return the StaticMarkerBinder singleton
|
||||
* @since 1.7.14
|
||||
*/
|
||||
public static StaticMarkerBinder getSingleton() {
|
||||
return SINGLETON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently this method always returns an instance of
|
||||
* {@link BasicMarkerFactory}.
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import org.apache.log4j.LogManager;
|
||||
import org.slf4j.helpers.Util;
|
||||
import org.slf4j.ILoggerFactory;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
|
|
@ -39,6 +40,23 @@ import org.slf4j.Logger;
|
|||
*/
|
||||
public class Log4jLoggerFactory implements ILoggerFactory {
|
||||
|
||||
private static final String LOG4J_DELEGATION_LOOP_URL = "http://www.slf4j.org/codes.html#log4jDelegationLoop";
|
||||
|
||||
// check for delegation loops
|
||||
static {
|
||||
try {
|
||||
Class.forName("org.apache.log4j.Log4jLoggerFactory");
|
||||
String part1 = "Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class path, preempting StackOverflowError. ";
|
||||
String part2 = "See also " + LOG4J_DELEGATION_LOOP_URL + " for more details.";
|
||||
|
||||
Util.report(part1);
|
||||
Util.report(part2);
|
||||
throw new IllegalStateException(part1 + part2);
|
||||
} catch (ClassNotFoundException e) {
|
||||
// this is the good case
|
||||
}
|
||||
}
|
||||
|
||||
// key: name (String), value: a Log4jLoggerAdapter;
|
||||
ConcurrentMap<String, Logger> loggerMap;
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,17 @@ public class StaticMDCBinder {
|
|||
|
||||
private StaticMDCBinder() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the singleton of this class.
|
||||
*
|
||||
* @return the StaticMDCBinder singleton
|
||||
* @since 1.7.14
|
||||
*/
|
||||
public static final StaticMDCBinder getSingleton() {
|
||||
return SINGLETON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently this method always returns an instance of
|
||||
* {@link StaticMDCBinder}.
|
||||
|
|
|
|||
|
|
@ -48,6 +48,16 @@ public class StaticMarkerBinder implements MarkerFactoryBinder {
|
|||
private StaticMarkerBinder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the singleton of this class.
|
||||
*
|
||||
* @return the StaticMarkerBinder singleton
|
||||
* @since 1.7.14
|
||||
*/
|
||||
public static StaticMarkerBinder getSingleton() {
|
||||
return SINGLETON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently this method always returns an instance of
|
||||
* {@link BasicMarkerFactory}.
|
||||
|
|
|
|||
|
|
@ -42,6 +42,16 @@ public class StaticMDCBinder {
|
|||
private StaticMDCBinder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the singleton of this class.
|
||||
*
|
||||
* @return the StaticMDCBinder singleton
|
||||
* @since 1.7.14
|
||||
*/
|
||||
public static final StaticMDCBinder getSingleton() {
|
||||
return SINGLETON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently this method always returns an instance of
|
||||
* {@link StaticMDCBinder}.
|
||||
|
|
|
|||
|
|
@ -48,6 +48,16 @@ public class StaticMarkerBinder implements MarkerFactoryBinder {
|
|||
private StaticMarkerBinder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the singleton of this class.
|
||||
*
|
||||
* @return the StaticMarkerBinder singleton
|
||||
* @since 1.7.14
|
||||
*/
|
||||
public static StaticMarkerBinder getSingleton() {
|
||||
return SINGLETON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently this method always returns an instance of
|
||||
* {@link BasicMarkerFactory}.
|
||||
|
|
|
|||
|
|
@ -42,6 +42,16 @@ public class StaticMDCBinder {
|
|||
private StaticMDCBinder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the singleton of this class.
|
||||
*
|
||||
* @return the StaticMDCBinder singleton
|
||||
* @since 1.7.14
|
||||
*/
|
||||
public static final StaticMDCBinder getSingleton() {
|
||||
return SINGLETON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently this method always returns an instance of
|
||||
* {@link StaticMDCBinder}.
|
||||
|
|
|
|||
|
|
@ -48,7 +48,17 @@ public class StaticMarkerBinder implements MarkerFactoryBinder {
|
|||
|
||||
private StaticMarkerBinder() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the singleton of this class.
|
||||
*
|
||||
* @return the StaticMarkerBinder singleton
|
||||
* @since 1.7.14
|
||||
*/
|
||||
public static StaticMarkerBinder getSingleton() {
|
||||
return SINGLETON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently this method always returns an instance of
|
||||
* {@link BasicMarkerFactory}.
|
||||
|
|
|
|||
|
|
@ -323,10 +323,11 @@ class B extends A {
|
|||
<p>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 <em>slf4j-log4j12.jar</em> and
|
||||
<em>log4j-over-slf4j.jar</em> are present on the class path, a
|
||||
<code>StackOverflowError</code> will inevitably occur immediately
|
||||
after the first invocation of an SLF4J or a log4j logger.
|
||||
logger to SLF4J. If SLF4J is bound with<em>slf4j-log4j12.jar</em>
|
||||
and <em>log4j-over-slf4j.jar</em> is also present on the class
|
||||
path, a <code>StackOverflowError</code> will inevitably occur
|
||||
immediately after the first invocation of an SLF4J or a log4j
|
||||
logger.
|
||||
</p>
|
||||
|
||||
<p>Here is how the exception might look like:</p>
|
||||
|
|
@ -371,11 +372,11 @@ class B extends A {
|
|||
<p>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
|
||||
<em>slf4j-jcl.jar</em> and <em>jcl-over-slf4j.jar</em> are present
|
||||
on the class path, then a <code>StackOverflowError</code> will
|
||||
inevitably occur immediately after the first invocation of an
|
||||
SLF4J or a JCL logger.
|
||||
calls made to a JCL logger to SLF4J. If SLF4J is bound with
|
||||
<em>slf4j-jcl.jar</em> and <em>jcl-over-slf4j.jar</em> is also
|
||||
present on the class path, then a <code>StackOverflowError</code>
|
||||
will inevitably occur immediately after the first invocation of an
|
||||
SLF4J or a JCL logger.
|
||||
</p>
|
||||
|
||||
<p>Here is how the exception might look like:</p>
|
||||
|
|
|
|||
|
|
@ -29,6 +29,52 @@
|
|||
|
||||
<hr noshade="noshade" size="1"/>
|
||||
|
||||
<h3>xxx January, 2016 - Release of SLF4J 1.7.14</h3>
|
||||
|
||||
|
||||
<p>The assignment of the INITIALIZATION_STATE variable in
|
||||
<code>LoggerFactory</code> is now guaranteed to be consistent for
|
||||
multi-thread initializations. More specifically, only one thread
|
||||
will see INITIALIZATION_STATE as UNINITIALIZED with all other
|
||||
threads observing either ONGOING_INITIALIZATION or the final result
|
||||
of the initialization. However, SLF4J initialization is still
|
||||
non-blocking and re-entrant, in the sense that if some thread tries
|
||||
to obtain loggers during ongoing initialization by another (or
|
||||
same) thread, instances of <code>SubstituteLogger</code> are
|
||||
returned. This fixes <a
|
||||
href="http://jira.qos.ch/browse/SLF4J-167">SLF4J-167</a> </p>.
|
||||
|
||||
|
||||
<p>Moved delegation check loop from <em>log4j-over-slf4j.jar</em>
|
||||
to <em>slf4j-log4j12.jar</em> for better targeted loop checks. The
|
||||
rationale behind the change is explained by Frans Orsel in <a
|
||||
href="http://jira.qos.ch/browse/SLF4J-345">SLF4J-345</a> who also
|
||||
provided the relevant pull request.
|
||||
</p>
|
||||
|
||||
<p>During initialization the binding ambiguity check is skipped
|
||||
under Android in order to improve performance. This change was
|
||||
requested by Nitin Verma in <a
|
||||
href="http://jira.qos.ch/browse/SLF4J-328">SLF4J-328</a> who also
|
||||
provided the relevant patch.
|
||||
</p>
|
||||
|
||||
<p>The <code>StaticMarkerBinder</code> and
|
||||
<code>StaticMDCBinder</code> classes shipping in various SLF4J
|
||||
bindings now offer a <code>getSingletion()</code> method. The
|
||||
<code>org.slf4j.MDC</code> and <code>MarkerFactory</code> classes
|
||||
now perform binding by invoking the <code>getSingleton()</code>
|
||||
method first and if in the presence of an older version of SLF4J
|
||||
with said method missing, then by accessing the SINGLETON
|
||||
field. This backward compatible change was requested by Rufus
|
||||
Alexander in <a
|
||||
href="http://jira.qos.ch/browse/SLF4J-347">SLF4J-347</a> in order
|
||||
to implement an SLF4J binding in Clojure, namely <a
|
||||
href="https://github.com/fzakaria/slf4j-timbre">slf4j-timbre</a>.
|
||||
</p>
|
||||
|
||||
<hr noshade="noshade" size="1"/>
|
||||
|
||||
<h3>10th of November, 2015 - Release of SLF4J 1.7.13</h3>
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue