diff --git a/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/Resources.java b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/Resources.java
index 980900cd965..66631c194e6 100644
--- a/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/Resources.java
+++ b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/Resources.java
@@ -16,15 +16,42 @@
*/
package org.apache.logging.log4j.test.junit;
+import aQute.bnd.annotation.baseline.BaselineIgnore;
import org.junit.jupiter.api.parallel.ResourceLock;
/**
* Constants to use the {@link ResourceLock} annotation.
- *
*/
-public class Resources {
+@BaselineIgnore("2.24.0")
+public final class Resources {
+
+ /**
+ * Marks tests that require access to {@link org.apache.logging.log4j.LogManager} methods or change its
+ * underlying {@link org.apache.logging.log4j.spi.LoggerContextFactory} implementation.
+ */
+ public static final String LOG_MANAGER = "log4j.LogManager";
+
+ /**
+ * Marks tests that require access to {@link org.apache.logging.log4j.ThreadContext} methods or change its
+ * underlying {@link org.apache.logging.log4j.spi.ThreadContextMap} implementation.
+ */
+ public static final String THREAD_CONTEXT = "log4j.ThreadContext";
+
+ /**
+ * Marks tests that require access to {@link org.apache.logging.log4j.MarkerManager} methods.
+ */
+ public static final String MARKER_MANAGER = "log4j.MarkerManager";
+
+ /**
+ * Marks tests that requires access to {@link org.apache.logging.log4j.Level} static methods to create new levels.
+ */
+ public static final String LEVEL = "log4j.Level";
- public static final String THREAD_CONTEXT = "log4j2.ThreadContext";
+ /**
+ * Marks tests that require access to {@link org.apache.logging.log4j.status.StatusLogger} static methods or
+ * change its underlying implementation.
+ */
+ public static final String STATUS_LOGGER = "log4j.StatusLogger";
- public static final String MARKER_MANAGER = "log4j2.MarkerManager";
+ private Resources() {}
}
diff --git a/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/package-info.java b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/package-info.java
index 22e32873bee..3207042de87 100644
--- a/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/package-info.java
+++ b/log4j-api-test/src/main/java/org/apache/logging/log4j/test/junit/package-info.java
@@ -15,7 +15,7 @@
* limitations under the license.
*/
@Export
-@Version("2.23.1")
+@Version("2.24.0")
package org.apache.logging.log4j.test.junit;
import org.osgi.annotation.bundle.Export;
diff --git a/log4j-api-test/src/test/java/org/apache/logging/log4j/internal/map/UnmodifiableArrayBackedMapTest.java b/log4j-api-test/src/test/java/org/apache/logging/log4j/internal/map/UnmodifiableArrayBackedMapTest.java
index efcee80a159..9652034d70f 100644
--- a/log4j-api-test/src/test/java/org/apache/logging/log4j/internal/map/UnmodifiableArrayBackedMapTest.java
+++ b/log4j-api-test/src/test/java/org/apache/logging/log4j/internal/map/UnmodifiableArrayBackedMapTest.java
@@ -24,6 +24,7 @@
import static org.junit.jupiter.api.Assertions.fail;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -31,6 +32,7 @@
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
import org.apache.logging.log4j.util.TriConsumer;
import org.junit.jupiter.api.Test;
@@ -238,32 +240,18 @@ public void testEqualsWhenOneValueDiffers() {
@Test
public void testForEachBiConsumer_JavaUtil() {
- UnmodifiableArrayBackedMap map = UnmodifiableArrayBackedMap.EMPTY_MAP.copyAndPutAll(getTestParameters());
- Set keys = new HashSet<>();
- java.util.function.BiConsumer java_util_action =
- new java.util.function.BiConsumer() {
- @Override
- public void accept(String key, String value) {
- keys.add(key);
- }
- };
- map.forEach(java_util_action);
+ final Map map = UnmodifiableArrayBackedMap.EMPTY_MAP.copyAndPutAll(getTestParameters());
+ final Collection keys = new HashSet<>();
+ map.forEach((key, value) -> keys.add(key));
assertEquals(map.keySet(), keys);
}
@Test
public void testForEachBiConsumer_Log4jUtil() {
- UnmodifiableArrayBackedMap map = UnmodifiableArrayBackedMap.EMPTY_MAP.copyAndPutAll(getTestParameters());
- Set keys = new HashSet<>();
- org.apache.logging.log4j.util.BiConsumer log4j_util_action =
- new org.apache.logging.log4j.util.BiConsumer() {
- @Override
- public void accept(String key, String value) {
- keys.add(key);
- }
- };
- map.forEach(log4j_util_action);
- assertEquals(map.keySet(), keys);
+ final ReadOnlyStringMap map = UnmodifiableArrayBackedMap.EMPTY_MAP.copyAndPutAll(getTestParameters());
+ final Collection keys = new HashSet<>();
+ map.forEach((key, value) -> keys.add(key));
+ assertEquals(map.toMap().keySet(), keys);
}
@Test
diff --git a/log4j-api-test/src/test/java/org/apache/logging/log4j/util/ServiceLoaderUtilTest.java b/log4j-api-test/src/test/java/org/apache/logging/log4j/util/ServiceLoaderUtilTest.java
index 09b489565c9..8ca74a0bee6 100644
--- a/log4j-api-test/src/test/java/org/apache/logging/log4j/util/ServiceLoaderUtilTest.java
+++ b/log4j-api-test/src/test/java/org/apache/logging/log4j/util/ServiceLoaderUtilTest.java
@@ -20,13 +20,15 @@
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.List;
import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
import java.util.stream.Collectors;
import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.status.StatusData;
+import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.test.BetterService;
import org.apache.logging.log4j.test.ListStatusListener;
import org.apache.logging.log4j.test.Service;
@@ -35,14 +37,26 @@
public class ServiceLoaderUtilTest {
+ private static final Logger LOGGER = StatusLogger.getLogger();
+
@Test
public void testServiceResolution() {
final List
*
- * @param value The value's whose class name should be used as the Logger name.
+ * @param value The value whose class name should be used as the Logger name.
* @return The Logger, created with a {@link StringFormatterMessageFactory}
* @throws UnsupportedOperationException if {@code value} is {@code null} and the calling class cannot be
* determined.
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/Logger.java b/log4j-api/src/main/java/org/apache/logging/log4j/Logger.java
index 7dc872e21a1..ef461ddfe31 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/Logger.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/Logger.java
@@ -200,7 +200,6 @@ public interface Logger {
* @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void debug(Marker marker, String message, Supplier>... paramSuppliers);
/**
@@ -222,7 +221,6 @@ public interface Logger {
* message factory.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void debug(Marker marker, Supplier> messageSupplier);
/**
@@ -235,7 +233,6 @@ public interface Logger {
* @param throwable A Throwable or null.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void debug(Marker marker, Supplier> messageSupplier, Throwable throwable);
/**
@@ -329,7 +326,6 @@ public interface Logger {
* @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void debug(String message, Supplier>... paramSuppliers);
/**
@@ -348,7 +344,6 @@ public interface Logger {
* message factory.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void debug(Supplier> messageSupplier);
/**
@@ -360,7 +355,6 @@ public interface Logger {
* @param throwable the {@code Throwable} to log, including its stack trace.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void debug(Supplier> messageSupplier, Throwable throwable);
/**
@@ -811,7 +805,6 @@ void debug(
* @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void error(Marker marker, String message, Supplier>... paramSuppliers);
/**
@@ -833,7 +826,6 @@ void debug(
* message factory.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void error(Marker marker, Supplier> messageSupplier);
/**
@@ -846,7 +838,6 @@ void debug(
* @param throwable A Throwable or null.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void error(Marker marker, Supplier> messageSupplier, Throwable throwable);
/**
@@ -940,7 +931,6 @@ void debug(
* @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void error(String message, Supplier>... paramSuppliers);
/**
@@ -959,7 +949,6 @@ void debug(
* message factory.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void error(Supplier> messageSupplier);
/**
@@ -971,7 +960,6 @@ void debug(
* @param throwable the {@code Throwable} to log, including its stack trace.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void error(Supplier> messageSupplier, Throwable throwable);
/**
@@ -1414,7 +1402,6 @@ void error(
* @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void fatal(Marker marker, String message, Supplier>... paramSuppliers);
/**
@@ -1436,7 +1423,6 @@ void error(
* message factory.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void fatal(Marker marker, Supplier> messageSupplier);
/**
@@ -1449,7 +1435,6 @@ void error(
* @param throwable A Throwable or null.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void fatal(Marker marker, Supplier> messageSupplier, Throwable throwable);
/**
@@ -1543,7 +1528,6 @@ void error(
* @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void fatal(String message, Supplier>... paramSuppliers);
/**
@@ -1562,7 +1546,6 @@ void error(
* message factory.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void fatal(Supplier> messageSupplier);
/**
@@ -1574,7 +1557,6 @@ void error(
* @param throwable the {@code Throwable} to log, including its stack trace.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void fatal(Supplier> messageSupplier, Throwable throwable);
/**
@@ -1901,12 +1883,13 @@ void fatal(
/**
* Gets the message factory used to convert message Objects and Strings/CharSequences into actual log Messages.
- *
- * Since version 2.6, Log4j internally uses message factories that implement the {@link MessageFactory2} interface.
- * From version 2.6.2, the return type of this method was changed from {@link MessageFactory} to
- * {@code MF}. The returned factory will always implement {@link MessageFactory2},
- * but the return type of this method could not be changed to {@link MessageFactory2} without breaking binary
- * compatibility.
+ *
+ * Since version 2.6, Log4j internally uses message factories that implement the {@link MessageFactory2}
+ * interface. From version 2.6.2, the return type of this method was changed from {@link MessageFactory} to
+ * {@code MF}. The returned factory will always implement {@link MessageFactory2},
+ * but the return type of this method could not be changed to {@link MessageFactory2} without breaking binary
+ * compatibility.
+ *
*
* @return the message factory, as an instance of {@link MessageFactory2}
*/
@@ -2030,7 +2013,6 @@ void fatal(
* @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void info(Marker marker, String message, Supplier>... paramSuppliers);
/**
@@ -2052,7 +2034,6 @@ void fatal(
* message factory.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void info(Marker marker, Supplier> messageSupplier);
/**
@@ -2065,7 +2046,6 @@ void fatal(
* @param throwable A Throwable or null.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void info(Marker marker, Supplier> messageSupplier, Throwable throwable);
/**
@@ -2159,7 +2139,6 @@ void fatal(
* @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void info(String message, Supplier>... paramSuppliers);
/**
@@ -2178,7 +2157,6 @@ void fatal(
* message factory.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void info(Supplier> messageSupplier);
/**
@@ -2190,7 +2168,6 @@ void fatal(
* @param throwable the {@code Throwable} to log, including its stack trace.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void info(Supplier> messageSupplier, Throwable throwable);
/**
@@ -2737,7 +2714,6 @@ void info(
* @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void log(Level level, Marker marker, String message, Supplier>... paramSuppliers);
/**
@@ -2760,7 +2736,6 @@ void info(
* message factory.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void log(Level level, Marker marker, Supplier> messageSupplier);
/**
@@ -2774,7 +2749,6 @@ void info(
* @param throwable A Throwable or null.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void log(Level level, Marker marker, Supplier> messageSupplier, Throwable throwable);
/**
@@ -2878,7 +2852,6 @@ void info(
* @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void log(Level level, String message, Supplier>... paramSuppliers);
/**
@@ -2899,7 +2872,6 @@ void info(
* message factory.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void log(Level level, Supplier> messageSupplier);
/**
@@ -2912,7 +2884,6 @@ void info(
* @param throwable the {@code Throwable} to log, including its stack log.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void log(Level level, Supplier> messageSupplier, Throwable throwable);
/**
@@ -3435,7 +3406,6 @@ void log(
* @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void trace(Marker marker, String message, Supplier>... paramSuppliers);
/**
@@ -3458,7 +3428,6 @@ void log(
* message factory.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void trace(Marker marker, Supplier> messageSupplier);
/**
@@ -3471,7 +3440,6 @@ void log(
* @param throwable A Throwable or null.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void trace(Marker marker, Supplier> messageSupplier, Throwable throwable);
/**
@@ -3567,7 +3535,6 @@ void log(
* @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void trace(String message, Supplier>... paramSuppliers);
/**
@@ -3587,7 +3554,6 @@ void log(
* message factory.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void trace(Supplier> messageSupplier);
/**
@@ -3599,7 +3565,6 @@ void log(
* @param throwable the {@code Throwable} to log, including its stack trace.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void trace(Supplier> messageSupplier, Throwable throwable);
/**
@@ -3967,7 +3932,6 @@ void trace(
*
* @since 2.6
*/
- @SuppressWarnings("deprecation")
EntryMessage traceEntry(Supplier>... paramSuppliers);
/**
@@ -3986,7 +3950,6 @@ void trace(
*
* @since 2.6
*/
- @SuppressWarnings("deprecation")
EntryMessage traceEntry(String format, Supplier>... paramSuppliers);
/**
@@ -4205,7 +4168,6 @@ void trace(
* @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void warn(Marker marker, String message, Supplier>... paramSuppliers);
/**
@@ -4227,7 +4189,6 @@ void trace(
* message factory.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void warn(Marker marker, Supplier> messageSupplier);
/**
@@ -4240,7 +4201,6 @@ void trace(
* @param throwable A Throwable or null.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void warn(Marker marker, Supplier> messageSupplier, Throwable throwable);
/**
@@ -4334,7 +4294,6 @@ void trace(
* @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void warn(String message, Supplier>... paramSuppliers);
/**
@@ -4353,7 +4312,6 @@ void trace(
* message factory.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void warn(Supplier> messageSupplier);
/**
@@ -4365,7 +4323,6 @@ void trace(
* @param throwable the {@code Throwable} to log, including its stack warn.
* @since 2.4
*/
- @SuppressWarnings("deprecation")
void warn(Supplier> messageSupplier, Throwable throwable);
/**
@@ -4695,7 +4652,12 @@ void warn(
* @since 2.13.0
*/
default void logMessage(
- Level level, Marker marker, String fqcn, StackTraceElement location, Message message, Throwable throwable) {
+ final Level level,
+ final Marker marker,
+ final String fqcn,
+ final StackTraceElement location,
+ final Message message,
+ final Throwable throwable) {
// noop
}
@@ -4768,7 +4730,7 @@ default LogBuilder always() {
* @return a LogBuilder.
* @since 2.13.0
*/
- default LogBuilder atLevel(Level level) {
+ default LogBuilder atLevel(final Level level) {
return LogBuilder.NOOP;
}
}
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/DefaultFlowMessageFactory.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/DefaultFlowMessageFactory.java
index 1c6fcd3f459..57dbd29b8ab 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/message/DefaultFlowMessageFactory.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/DefaultFlowMessageFactory.java
@@ -17,8 +17,6 @@
package org.apache.logging.log4j.message;
import java.io.Serializable;
-import org.apache.logging.log4j.spi.AbstractLogger;
-import org.apache.logging.log4j.util.LoaderUtil;
import org.apache.logging.log4j.util.StringBuilderFormattable;
import org.apache.logging.log4j.util.StringBuilders;
import org.apache.logging.log4j.util.Strings;
@@ -34,9 +32,10 @@ public class DefaultFlowMessageFactory implements FlowMessageFactory, Serializab
private static final String ENTRY_DEFAULT_PREFIX = "Enter";
private static final long serialVersionUID = 8578655591131397576L;
+ public static final FlowMessageFactory INSTANCE = new DefaultFlowMessageFactory();
+
private final String entryText;
private final String exitText;
- private final MessageFactory messageFactory;
/**
* Constructs a message factory with {@code "Enter"} and {@code "Exit"} as the default flow strings.
@@ -53,15 +52,6 @@ public DefaultFlowMessageFactory() {
public DefaultFlowMessageFactory(final String entryText, final String exitText) {
this.entryText = entryText;
this.exitText = exitText;
- this.messageFactory = createDefaultMessageFactory();
- }
-
- private static MessageFactory createDefaultMessageFactory() {
- try {
- return LoaderUtil.newInstanceOf(AbstractLogger.DEFAULT_MESSAGE_FACTORY_CLASS);
- } catch (final ReflectiveOperationException e) {
- throw new IllegalStateException(e);
- }
}
private static class AbstractFlowMessage implements FlowMessage, StringBuilderFormattable {
@@ -194,9 +184,9 @@ public EntryMessage newEntryMessage(final String format, final Object... params)
final boolean hasFormat = Strings.isNotEmpty(format);
final Message message;
if (params == null || params.length == 0) {
- message = hasFormat ? messageFactory.newMessage(format) : null;
+ message = hasFormat ? ParameterizedMessageFactory.INSTANCE.newMessage(format) : null;
} else if (hasFormat) {
- message = messageFactory.newMessage(format, params);
+ message = ParameterizedMessageFactory.INSTANCE.newMessage(format, params);
} else {
final StringBuilder sb = new StringBuilder("params(");
for (int i = 0; i < params.length; i++) {
@@ -206,7 +196,7 @@ public EntryMessage newEntryMessage(final String format, final Object... params)
sb.append("{}");
}
sb.append(")");
- message = messageFactory.newMessage(sb.toString(), params);
+ message = ParameterizedMessageFactory.INSTANCE.newMessage(sb.toString(), params);
}
return newEntryMessage(message);
}
@@ -233,9 +223,9 @@ public ExitMessage newExitMessage(final String format, final Object result) {
final boolean hasFormat = Strings.isNotEmpty(format);
final Message message;
if (result == null) {
- message = hasFormat ? messageFactory.newMessage(format) : null;
+ message = hasFormat ? ParameterizedMessageFactory.INSTANCE.newMessage(format) : null;
} else {
- message = messageFactory.newMessage(hasFormat ? format : "with({})", result);
+ message = ParameterizedMessageFactory.INSTANCE.newMessage(hasFormat ? format : "with({})", result);
}
return newExitMessage(message);
}
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
index d55b98ae700..053a5bf8f1c 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ReusableParameterizedMessage.java
@@ -135,26 +135,27 @@ private static Throwable determineThrowable(final Object[] args, final int argCo
return null;
}
- ReusableParameterizedMessage set(final String messagePattern, final Object... arguments) {
+ public ReusableParameterizedMessage set(final String messagePattern, final Object... arguments) {
init(messagePattern, arguments == null ? 0 : arguments.length, arguments);
varargs = arguments;
return this;
}
- ReusableParameterizedMessage set(final String messagePattern, final Object p0) {
+ public ReusableParameterizedMessage set(final String messagePattern, final Object p0) {
params[0] = p0;
init(messagePattern, 1, params);
return this;
}
- ReusableParameterizedMessage set(final String messagePattern, final Object p0, final Object p1) {
+ public ReusableParameterizedMessage set(final String messagePattern, final Object p0, final Object p1) {
params[0] = p0;
params[1] = p1;
init(messagePattern, 2, params);
return this;
}
- ReusableParameterizedMessage set(final String messagePattern, final Object p0, final Object p1, final Object p2) {
+ public ReusableParameterizedMessage set(
+ final String messagePattern, final Object p0, final Object p1, final Object p2) {
params[0] = p0;
params[1] = p1;
params[2] = p2;
@@ -162,7 +163,7 @@ ReusableParameterizedMessage set(final String messagePattern, final Object p0, f
return this;
}
- ReusableParameterizedMessage set(
+ public ReusableParameterizedMessage set(
final String messagePattern, final Object p0, final Object p1, final Object p2, final Object p3) {
params[0] = p0;
params[1] = p1;
@@ -172,7 +173,7 @@ ReusableParameterizedMessage set(
return this;
}
- ReusableParameterizedMessage set(
+ public ReusableParameterizedMessage set(
final String messagePattern,
final Object p0,
final Object p1,
@@ -188,7 +189,7 @@ ReusableParameterizedMessage set(
return this;
}
- ReusableParameterizedMessage set(
+ public ReusableParameterizedMessage set(
final String messagePattern,
final Object p0,
final Object p1,
@@ -206,7 +207,7 @@ ReusableParameterizedMessage set(
return this;
}
- ReusableParameterizedMessage set(
+ public ReusableParameterizedMessage set(
final String messagePattern,
final Object p0,
final Object p1,
@@ -226,7 +227,7 @@ ReusableParameterizedMessage set(
return this;
}
- ReusableParameterizedMessage set(
+ public ReusableParameterizedMessage set(
final String messagePattern,
final Object p0,
final Object p1,
@@ -248,7 +249,7 @@ ReusableParameterizedMessage set(
return this;
}
- ReusableParameterizedMessage set(
+ public ReusableParameterizedMessage set(
final String messagePattern,
final Object p0,
final Object p1,
@@ -272,7 +273,7 @@ ReusableParameterizedMessage set(
return this;
}
- ReusableParameterizedMessage set(
+ public ReusableParameterizedMessage set(
final String messagePattern,
final Object p0,
final Object p1,
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java
index 18ed7befe4f..4ddbdc5c5f4 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/ThreadDumpMessage.java
@@ -24,10 +24,11 @@
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
-import java.lang.invoke.MethodHandles;
import java.util.HashMap;
import java.util.Map;
+import java.util.ServiceLoader;
import org.apache.logging.log4j.message.ThreadDumpMessage.ThreadInfoFactory;
+import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.util.Lazy;
import org.apache.logging.log4j.util.ServiceLoaderUtil;
import org.apache.logging.log4j.util.StringBuilderFormattable;
@@ -61,7 +62,10 @@ private ThreadDumpMessage(final String formattedMsg, final String title) {
}
private static ThreadInfoFactory initFactory() {
- return ServiceLoaderUtil.loadServices(ThreadInfoFactory.class, MethodHandles.lookup(), false)
+ return ServiceLoaderUtil.safeStream(
+ ThreadInfoFactory.class,
+ ServiceLoader.load(ThreadInfoFactory.class, ThreadDumpMessage.class.getClassLoader()),
+ StatusLogger.getLogger())
.findFirst()
.orElseGet(BasicThreadInfoFactory::new);
}
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/package-info.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/package-info.java
index 49286fab779..24632f8d7b5 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/message/package-info.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/package-info.java
@@ -22,7 +22,7 @@
/**
* Bumped to 2.22.0, since FormattedMessage behavior changed.
*/
-@Version("2.22.0")
+@Version("2.24.0")
package org.apache.logging.log4j.message;
import org.osgi.annotation.bundle.Export;
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java
index d9543f17b52..30d0cffef02 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractLogger.java
@@ -35,7 +35,6 @@
import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.util.Constants;
import org.apache.logging.log4j.util.LambdaUtil;
-import org.apache.logging.log4j.util.LoaderUtil;
import org.apache.logging.log4j.util.MessageSupplier;
import org.apache.logging.log4j.util.PerformanceSensitive;
import org.apache.logging.log4j.util.StackLocatorUtil;
@@ -198,12 +197,7 @@ protected Message catchingMsg(final Throwable throwable) {
}
private static MessageFactory2 createDefaultMessageFactory() {
- try {
- final MessageFactory result = LoaderUtil.newInstanceOf(DEFAULT_MESSAGE_FACTORY_CLASS);
- return narrow(result);
- } catch (final ReflectiveOperationException e) {
- throw new IllegalStateException(e);
- }
+ return ParameterizedMessageFactory.INSTANCE;
}
private static MessageFactory2 narrow(final MessageFactory result) {
@@ -214,11 +208,7 @@ private static MessageFactory2 narrow(final MessageFactory result) {
}
private static FlowMessageFactory createDefaultFlowMessageFactory() {
- try {
- return LoaderUtil.newInstanceOf(DEFAULT_FLOW_MESSAGE_FACTORY_CLASS);
- } catch (final ReflectiveOperationException e) {
- throw new IllegalStateException(e);
- }
+ return DefaultFlowMessageFactory.INSTANCE;
}
@Override
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/BiConsumer.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/BiConsumer.java
index 7be09f0431b..e7cedb6bb3b 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/BiConsumer.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/BiConsumer.java
@@ -24,12 +24,14 @@
* @see ReadOnlyStringMap
* @since 2.7
*/
-public interface BiConsumer {
+@FunctionalInterface
+public interface BiConsumer extends java.util.function.BiConsumer {
/**
* Performs the operation given the specified arguments.
* @param k the first input argument
* @param v the second input argument
*/
+ @Override
void accept(K k, V v);
}
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/LambdaUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/LambdaUtil.java
index bab3171e7f3..ef1f3b0b321 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/LambdaUtil.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/LambdaUtil.java
@@ -35,7 +35,6 @@ private LambdaUtil() {}
* @return an array containing the results of evaluating the lambda expressions (or {@code null} if the suppliers
* array was {@code null}
*/
- @SuppressWarnings("deprecation")
public static Object[] getAll(final Supplier>... suppliers) {
if (suppliers == null) {
return null;
@@ -54,7 +53,6 @@ public static Object[] getAll(final Supplier>... suppliers) {
* @return the results of evaluating the lambda expression (or {@code null} if the supplier
* was {@code null}
*/
- @SuppressWarnings("deprecation")
public static Object get(final Supplier> supplier) {
if (supplier == null) {
return null;
@@ -83,7 +81,6 @@ public static Message get(final MessageSupplier supplier) {
* @return the Message resulting from evaluating the lambda expression or the Message created by the factory for
* supplied values that are not of type Message
*/
- @SuppressWarnings("deprecation")
public static Message getMessage(final Supplier> supplier, final MessageFactory messageFactory) {
if (supplier == null) {
return null;
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/MessageSupplier.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/MessageSupplier.java
index 8b135713505..d3776a1a744 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/MessageSupplier.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/MessageSupplier.java
@@ -33,12 +33,14 @@
*
* @since 2.4
*/
-public interface MessageSupplier {
+@FunctionalInterface
+public interface MessageSupplier extends Supplier {
/**
* Gets a Message.
*
* @return a Message
*/
+ @Override
Message get();
}
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/OsgiServiceLocator.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/OsgiServiceLocator.java
index d061ccbd6db..46157290c18 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/OsgiServiceLocator.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/OsgiServiceLocator.java
@@ -24,6 +24,7 @@
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.wiring.BundleRevision;
public class OsgiServiceLocator {
@@ -57,29 +58,53 @@ public static Stream loadServices(final Class serviceType, final Looku
public static Stream loadServices(final Class serviceType, final Lookup lookup, final boolean verbose) {
final Class> lookupClass = Objects.requireNonNull(lookup, "lookup").lookupClass();
- final Bundle bundle = FrameworkUtil.getBundle(Objects.requireNonNull(lookupClass, "lookupClass"));
- if (bundle != null) {
+ return loadServices(serviceType, lookupClass, StatusLogger.getLogger());
+ }
+
+ static Stream loadServices(final Class serviceType, final Class> callerClass, final Logger logger) {
+ final Bundle bundle = FrameworkUtil.getBundle(callerClass);
+ if (bundle != null && !isFragment(bundle)) {
final BundleContext ctx = bundle.getBundleContext();
if (ctx == null) {
- if (verbose) {
- StatusLogger.getLogger()
- .error(
- "Unable to load OSGI services: The bundle has no valid BundleContext for serviceType = {}, lookup = {}, lookupClass = {}, bundle = {}",
- serviceType,
- lookup,
- lookupClass,
- bundle);
- }
+ logger.warn(
+ "Unable to load OSGi services for service {}: bundle {} (state {}) does not have a valid BundleContext",
+ serviceType::getName,
+ bundle::getSymbolicName,
+ () -> {
+ switch (bundle.getState()) {
+ case Bundle.UNINSTALLED:
+ return "UNINSTALLED";
+ case Bundle.INSTALLED:
+ return "INSTALLED";
+ case Bundle.RESOLVED:
+ return "RESOLVED";
+ case Bundle.STARTING:
+ return "STARTING";
+ case Bundle.STOPPING:
+ return "STOPPING";
+ case Bundle.ACTIVE:
+ return "ACTIVE";
+ default:
+ return "UNKNOWN";
+ }
+ });
+
} else {
try {
return ctx.getServiceReferences(serviceType, null).stream().map(ctx::getService);
- } catch (Throwable e) {
- if (verbose) {
- StatusLogger.getLogger().error("Unable to load OSGI services for service {}", serviceType, e);
- }
+ } catch (final Exception e) {
+ logger.error("Unable to load OSGI services for service {}", serviceType, e);
}
}
}
return Stream.empty();
}
+
+ private static boolean isFragment(final Bundle bundle) {
+ try {
+ return (bundle.adapt(BundleRevision.class).getTypes() & BundleRevision.TYPE_FRAGMENT) != 0;
+ } catch (final SecurityException ignored) {
+ return false;
+ }
+ }
}
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
index daf9163203a..310f432edd4 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
@@ -21,7 +21,6 @@
import aQute.bnd.annotation.spi.ServiceConsumer;
import java.io.IOException;
import java.io.InputStream;
-import java.lang.invoke.MethodHandles;
import java.nio.charset.Charset;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
@@ -486,7 +485,10 @@ private Environment(final PropertySource propertySource) {
}
sources.add(propertySource);
// We don't log anything on the status logger.
- ServiceLoaderUtil.loadServices(PropertySource.class, MethodHandles.lookup(), false, false)
+ ServiceLoaderUtil.safeStream(
+ PropertySource.class,
+ ServiceLoader.load(PropertySource.class, PropertiesUtil.class.getClassLoader()),
+ LOGGER)
.forEach(sources::add);
reload();
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/ProviderUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/ProviderUtil.java
index a669bf71433..c02526b4a0e 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/ProviderUtil.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/ProviderUtil.java
@@ -24,13 +24,13 @@
import aQute.bnd.annotation.spi.ServiceConsumer;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
-import java.lang.invoke.MethodHandles;
import java.net.URL;
import java.util.Collection;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Properties;
+import java.util.ServiceLoader;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;
@@ -152,7 +152,10 @@ static void lazyInit() {
STARTUP_LOCK.lockInterruptibly();
try {
if (PROVIDER == null) {
- ServiceLoaderUtil.loadServices(Provider.class, MethodHandles.lookup(), false)
+ ServiceLoaderUtil.safeStream(
+ Provider.class,
+ ServiceLoader.load(Provider.class, ProviderUtil.class.getClassLoader()),
+ LOGGER)
.filter(provider -> validVersion(provider.getVersions()))
.forEach(ProviderUtil::addProvider);
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceLoaderUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceLoaderUtil.java
index cf906eab69b..30b56f83b56 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceLoaderUtil.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/ServiceLoaderUtil.java
@@ -16,30 +16,41 @@
*/
package org.apache.logging.log4j.util;
-import java.lang.invoke.CallSite;
-import java.lang.invoke.LambdaMetafactory;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles.Lookup;
-import java.lang.invoke.MethodType;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.util.Collections;
+import static java.util.Objects.requireNonNull;
+
+import aQute.bnd.annotation.baseline.BaselineIgnore;
+import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
-import java.util.Set;
-import java.util.Spliterator;
+import java.util.Spliterators;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.apache.logging.log4j.Logger;
-import org.apache.logging.log4j.status.StatusLogger;
/**
- * This class should be considered internal.
+ * An utility class to retrieve services in a safe way.
+ *
+ * This class should be considered internal.
+ *
+ *
+ * A common source of {@link ServiceLoader} failures, when running in a multi-classloader environment, is the
+ * presence of multiple classes with the same class name in the same classloader hierarchy. Since {@code
+ * ServiceLoader} retrieves services by class name, it is entirely possible that the registered services don't
+ * extend the required interface and cause an exception to be thrown by {@code ServiceLoader}.
+ *
+ *
+ * The purpose of this class is to:
+ *
+ *
+ *
skip faulty services, allowing for a partial retrieval of the good ones,
+ *
allow to integrate other sources of services like OSGi services.
+ *
*/
@InternalApi
+@BaselineIgnore("2.24.0")
public final class ServiceLoaderUtil {
private static final int MAX_BROKEN_SERVICES = 8;
@@ -47,110 +58,43 @@ public final class ServiceLoaderUtil {
private ServiceLoaderUtil() {}
/**
- * Retrieves the available services from the caller's classloader.
- *
- * Broken services will be ignored.
- *
- * @param The service type.
- * @param serviceType The class of the service.
- * @param lookup The calling class data.
- * @return A stream of service instances.
- */
- public static Stream loadServices(final Class serviceType, final Lookup lookup) {
- return loadServices(serviceType, lookup, false);
- }
-
- /**
- * Retrieves the available services from the caller's classloader and possibly
- * the thread context classloader.
- *
- * Broken services will be ignored.
- *
- * @param The service type.
- * @param serviceType The class of the service.
- * @param lookup The calling class data.
- * @param useTccl If true the thread context classloader will also be used.
- * @return A stream of service instances.
+ * Retrieves services registered with {@link ServiceLoader}
+ *
+ * It ignores the most common service loading errors.
+ *
+ * @param serviceType The service type to use for OSGi service retrieval.
+ * @param serviceLoader The service loader instance to use.
+ * @param logger The logger to use to report service failures.
+ * @return A stream of all correctly loaded services.
+ * @since 2.24.0
*/
- public static Stream loadServices(final Class serviceType, final Lookup lookup, final boolean useTccl) {
- return loadServices(serviceType, lookup, useTccl, true);
- }
-
- static Stream loadServices(
- final Class serviceType, final Lookup lookup, final boolean useTccl, final boolean verbose) {
- final ClassLoader classLoader = lookup.lookupClass().getClassLoader();
- Stream services = loadClassloaderServices(serviceType, lookup, classLoader, verbose);
- if (useTccl) {
- final ClassLoader contextClassLoader = LoaderUtil.getThreadContextClassLoader();
- if (contextClassLoader != classLoader) {
- services = Stream.concat(
- services, loadClassloaderServices(serviceType, lookup, contextClassLoader, verbose));
- }
- }
- if (OsgiServiceLocator.isAvailable()) {
- services = Stream.concat(services, OsgiServiceLocator.loadServices(serviceType, lookup, verbose));
- }
- final Set> classes = new HashSet<>();
- // only the first occurrence of a class
- return services.filter(service -> classes.add(service.getClass()));
- }
-
- static Stream loadClassloaderServices(
- final Class serviceType, final Lookup lookup, final ClassLoader classLoader, final boolean verbose) {
- return StreamSupport.stream(new ServiceLoaderSpliterator(serviceType, lookup, classLoader, verbose), false);
+ public static Stream safeStream(
+ final Class serviceType, final ServiceLoader extends S> serviceLoader, final Logger logger) {
+ requireNonNull(serviceLoader, "serviceLoader");
+ final Collection> classes = new HashSet<>();
+ final Stream services =
+ StreamSupport.stream(new ServiceLoaderSpliterator<>(serviceType, serviceLoader, logger), false);
+ // Caller class may be null
+ final Class> callerClass = StackLocatorUtil.getCallerClass(2);
+ final Stream allServices = OsgiServiceLocator.isAvailable() && callerClass != null
+ ? Stream.concat(services, OsgiServiceLocator.loadServices(serviceType, callerClass, logger))
+ : services;
+ return allServices
+ // only the first occurrence of a class
+ .filter(service -> classes.add(service.getClass()));
}
- static Iterable callServiceLoader(
- final Lookup lookup, final Class serviceType, final ClassLoader classLoader, final boolean verbose) {
- try {
- // Creates a lambda in the caller's domain that calls `ServiceLoader`
- final MethodHandle loadHandle = lookup.findStatic(
- ServiceLoader.class,
- "load",
- MethodType.methodType(ServiceLoader.class, Class.class, ClassLoader.class));
- final CallSite callSite = LambdaMetafactory.metafactory(
- lookup,
- "run",
- MethodType.methodType(PrivilegedAction.class, Class.class, ClassLoader.class),
- MethodType.methodType(Object.class),
- loadHandle,
- MethodType.methodType(ServiceLoader.class));
- final PrivilegedAction> action = (PrivilegedAction>)
- callSite.getTarget() //
- .bindTo(serviceType)
- .bindTo(classLoader)
- .invoke();
- final ServiceLoader serviceLoader;
- if (System.getSecurityManager() == null) {
- serviceLoader = action.run();
- } else {
- final MethodHandle privilegedHandle = lookup.findStatic(
- AccessController.class,
- "doPrivileged",
- MethodType.methodType(Object.class, PrivilegedAction.class));
- serviceLoader = (ServiceLoader) privilegedHandle.invoke(action);
- }
- return serviceLoader;
- } catch (Throwable e) {
- if (verbose) {
- StatusLogger.getLogger().error("Unable to load services for service {}", serviceType, e);
- }
- }
- return Collections.emptyList();
- }
-
- private static class ServiceLoaderSpliterator implements Spliterator {
-
- private final Iterator serviceIterator;
- private final Logger logger;
+ private static final class ServiceLoaderSpliterator extends Spliterators.AbstractSpliterator {
private final String serviceName;
+ private final Iterator extends S> serviceIterator;
+ private final Logger logger;
- public ServiceLoaderSpliterator(
- final Class serviceType, final Lookup lookup, final ClassLoader classLoader, final boolean verbose) {
- this.serviceIterator =
- callServiceLoader(lookup, serviceType, classLoader, verbose).iterator();
- this.logger = verbose ? StatusLogger.getLogger() : null;
- this.serviceName = serviceType.toString();
+ private ServiceLoaderSpliterator(
+ final Class serviceType, final Iterable extends S> serviceLoader, final Logger logger) {
+ super(Long.MAX_VALUE, ORDERED | NONNULL | IMMUTABLE);
+ this.serviceName = serviceType.getName();
+ this.serviceIterator = serviceLoader.iterator();
+ this.logger = logger;
}
@Override
@@ -162,33 +106,14 @@ public boolean tryAdvance(final Consumer super S> action) {
action.accept(serviceIterator.next());
return true;
}
- } catch (ServiceConfigurationError | LinkageError e) {
- if (logger != null) {
- logger.warn("Unable to load service class for service {}", serviceName, e);
- }
- } catch (Throwable e) {
- if (logger != null) {
- logger.warn("Unable to load service class for service {}", serviceName, e);
- }
+ } catch (final ServiceConfigurationError | LinkageError e) {
+ logger.warn("Unable to load implementation for service {}", serviceName, e);
+ } catch (final Exception e) {
+ logger.warn("Unexpected exception while loading implementation for service {}", serviceName, e);
throw e;
}
}
return false;
}
-
- @Override
- public Spliterator trySplit() {
- return null;
- }
-
- @Override
- public long estimateSize() {
- return Long.MAX_VALUE;
- }
-
- @Override
- public int characteristics() {
- return NONNULL | IMMUTABLE;
- }
}
}
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/StackLocator.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/StackLocator.java
index bc20af0daf3..e5b50fc7ca2 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/StackLocator.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/StackLocator.java
@@ -69,7 +69,10 @@ public final class StackLocator {
Method getCallerClassMethod;
int java7u25CompensationOffset = 0;
try {
- final Class> sunReflectionClass = LoaderUtil.loadClass("sun.reflect.Reflection");
+ // Do not use `LoaderUtil` here, since it causes a cycle of dependencies:
+ // LoaderUtil -> PropertiesUtil -> ServiceLoaderUtil -> StackLocator
+ final Class> sunReflectionClass =
+ Class.forName("sun.reflect.Reflection", true, ClassLoader.getSystemClassLoader());
getCallerClassMethod = sunReflectionClass.getDeclaredMethod("getCallerClass", int.class);
Object o = getCallerClassMethod.invoke(null, 0);
getCallerClassMethod.invoke(null, 0);
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/Supplier.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/Supplier.java
index aaa4d9b89a1..45ad5c667d2 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/Supplier.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/Supplier.java
@@ -31,14 +31,15 @@
*
* @since 2.4
*/
+@FunctionalInterface
@InternalApi
-@Deprecated
-public interface Supplier {
+public interface Supplier extends java.util.function.Supplier {
/**
* Gets a value.
*
* @return a value
*/
+ @Override
T get();
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SmtpAppender.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SmtpAppender.java
index c1299311eaa..b610603b4be 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SmtpAppender.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/SmtpAppender.java
@@ -17,7 +17,7 @@
package org.apache.logging.log4j.core.appender;
import java.io.Serializable;
-import java.lang.invoke.MethodHandles;
+import java.util.ServiceLoader;
import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Core;
import org.apache.logging.log4j.core.Filter;
@@ -45,6 +45,7 @@
import org.apache.logging.log4j.core.net.ssl.SslConfiguration;
import org.apache.logging.log4j.core.util.Booleans;
import org.apache.logging.log4j.core.util.Integers;
+import org.apache.logging.log4j.status.StatusLogger;
import org.apache.logging.log4j.util.ServiceLoaderUtil;
import org.apache.logging.log4j.util.Strings;
@@ -300,8 +301,11 @@ public SmtpAppender build() {
bufferSize,
sslConfiguration,
getFilter().toString());
- final MailManagerFactory factory = ServiceLoaderUtil.loadServices(
- MailManagerFactory.class, MethodHandles.lookup())
+ final MailManagerFactory factory = ServiceLoaderUtil.safeStream(
+ MailManagerFactory.class,
+ ServiceLoader.load(
+ MailManagerFactory.class, getClass().getClassLoader()),
+ StatusLogger.getLogger())
.findAny()
.orElseGet(() -> SmtpManager.FACTORY);
final MailManager smtpManager = AbstractManager.getManager(data.getManagerName(), factory, data);
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjector.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjector.java
index 24f34936e6d..332b877a51f 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjector.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/ThreadContextDataInjector.java
@@ -19,13 +19,13 @@
import aQute.bnd.annotation.Cardinality;
import aQute.bnd.annotation.Resolution;
import aQute.bnd.annotation.spi.ServiceConsumer;
-import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentLinkedDeque;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.ThreadContext;
@@ -79,7 +79,10 @@ public static void initServiceProviders() {}
private static List getServiceProviders() {
final List providers = new ArrayList<>();
- ServiceLoaderUtil.loadServices(ContextDataProvider.class, MethodHandles.lookup(), false)
+ ServiceLoaderUtil.safeStream(
+ ContextDataProvider.class,
+ ServiceLoader.load(ContextDataProvider.class, ThreadContextDataInjector.class.getClassLoader()),
+ LOGGER)
.forEach(providers::add);
return Collections.unmodifiableList(providers);
}
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatchManager.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatchManager.java
index 491c212f6f0..1761498087b 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatchManager.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/util/WatchManager.java
@@ -20,12 +20,12 @@
import aQute.bnd.annotation.Resolution;
import aQute.bnd.annotation.spi.ServiceConsumer;
import java.io.File;
-import java.lang.invoke.MethodHandles;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.ServiceLoader;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -143,7 +143,8 @@ public void run() {
public WatchManager(final ConfigurationScheduler scheduler) {
this.scheduler = Objects.requireNonNull(scheduler, "scheduler");
- eventServiceList = ServiceLoaderUtil.loadServices(WatchEventService.class, MethodHandles.lookup(), true)
+ eventServiceList = ServiceLoaderUtil.safeStream(
+ WatchEventService.class, ServiceLoader.load(WatchEventService.class), logger)
.collect(Collectors.toList());
}
diff --git a/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/JULProvider.java b/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/JULProvider.java
index 9022d9abeb8..0f371f43ef0 100644
--- a/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/JULProvider.java
+++ b/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/JULProvider.java
@@ -18,6 +18,7 @@
import aQute.bnd.annotation.Resolution;
import aQute.bnd.annotation.spi.ServiceProvider;
+import org.apache.logging.log4j.spi.LoggerContextFactory;
import org.apache.logging.log4j.spi.Provider;
/**
@@ -27,7 +28,20 @@
*/
@ServiceProvider(value = Provider.class, resolution = Resolution.OPTIONAL)
public class JULProvider extends Provider {
+ private static final LoggerContextFactory CONTEXT_FACTORY = new JULLoggerContextFactory();
+
public JULProvider() {
- super(20, "2.6.0", JULLoggerContextFactory.class, null);
+ super(20, CURRENT_VERSION);
+ }
+
+ @Override
+ public LoggerContextFactory getLoggerContextFactory() {
+ return CONTEXT_FACTORY;
+ }
+
+ @Override
+ public String getThreadContextMap() {
+ // JUL does not provide an MDC implementation
+ return NO_OP_CONTEXT_MAP;
}
}
diff --git a/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/package-info.java b/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/package-info.java
index f333fffe246..aa117c7995c 100644
--- a/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/package-info.java
+++ b/log4j-to-jul/src/main/java/org/apache/logging/log4j/tojul/package-info.java
@@ -21,7 +21,7 @@
* @author Michael Vorburger.ch for Google
*/
@Export
-@Version("2.20.1")
+@Version("2.24.0")
package org.apache.logging.log4j.tojul;
import org.osgi.annotation.bundle.Export;
diff --git a/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/SLF4JProvider.java b/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/SLF4JProvider.java
index b8514c4f632..318d7937f66 100644
--- a/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/SLF4JProvider.java
+++ b/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/SLF4JProvider.java
@@ -18,14 +18,30 @@
import aQute.bnd.annotation.Resolution;
import aQute.bnd.annotation.spi.ServiceProvider;
+import org.apache.logging.log4j.spi.LoggerContextFactory;
import org.apache.logging.log4j.spi.Provider;
+import org.apache.logging.log4j.spi.ThreadContextMap;
/**
* Bind the Log4j API to SLF4J.
*/
@ServiceProvider(value = Provider.class, resolution = Resolution.OPTIONAL)
public class SLF4JProvider extends Provider {
+
+ private static final LoggerContextFactory CONTEXT_FACTORY = new SLF4JLoggerContextFactory();
+ private static final ThreadContextMap THREAD_CONTEXT_MAP = new MDCContextMap();
+
public SLF4JProvider() {
- super(15, "2.6.0", SLF4JLoggerContextFactory.class, MDCContextMap.class);
+ super(15, CURRENT_VERSION);
+ }
+
+ @Override
+ public LoggerContextFactory getLoggerContextFactory() {
+ return CONTEXT_FACTORY;
+ }
+
+ @Override
+ public ThreadContextMap getThreadContextMapInstance() {
+ return THREAD_CONTEXT_MAP;
}
}
diff --git a/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/package-info.java b/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/package-info.java
index e354601ca71..ba4cb130be1 100644
--- a/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/package-info.java
+++ b/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/package-info.java
@@ -18,7 +18,7 @@
* SLF4J support.
*/
@Export
-@Version("2.20.1")
+@Version("2.24.0")
package org.apache.logging.slf4j;
import org.osgi.annotation.bundle.Export;
diff --git a/src/changelog/.2.x.x/1539_graalvm_friendly.xml b/src/changelog/.2.x.x/1539_graalvm_friendly.xml
new file mode 100644
index 00000000000..74964f43564
--- /dev/null
+++ b/src/changelog/.2.x.x/1539_graalvm_friendly.xml
@@ -0,0 +1,8 @@
+
+
+
+ Fix usage of `log4j-api` in GraalVM without additional reachability data.
+