This is an automated email from the ASF dual-hosted git repository. pkarwasz pushed a commit to branch fix/backport-log4j3-api in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit b755ffe6cfa4f5a16a2856f2cc111e8ee0ee1114 Author: Piotr P. Karwasz <[email protected]> AuthorDate: Thu Mar 14 15:58:42 2024 +0100 Simplify `ServiceLoaderUtil` We make `ServiceLoaderUtil` more GraalVM-friendly by replacing the usage of `MethodHandles.Lookup` with the requirement for the caller to instantiate the `ServiceLoader` himself. --- .../logging/log4j/util/ServiceLoaderUtilTest.java | 25 ++- .../logging/log4j/message/ThreadDumpMessage.java | 8 +- .../logging/log4j/util/OsgiServiceLocator.java | 55 ++++-- .../apache/logging/log4j/util/PropertiesUtil.java | 6 +- .../apache/logging/log4j/util/ProviderUtil.java | 7 +- .../logging/log4j/util/ServiceLoaderUtil.java | 193 +++++++-------------- .../apache/logging/log4j/util/StackLocator.java | 4 +- .../logging/log4j/core/appender/SmtpAppender.java | 10 +- .../log4j/core/impl/ThreadContextDataInjector.java | 7 +- .../logging/log4j/core/util/WatchManager.java | 5 +- 10 files changed, 153 insertions(+), 167 deletions(-) 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 09b489565c..8ca74a0bee 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.assertj.core.api.Assertions.assertThat; 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 @@ import org.junit.jupiter.api.Test; public class ServiceLoaderUtilTest { + private static final Logger LOGGER = StatusLogger.getLogger(); + @Test public void testServiceResolution() { final List<Object> services = new ArrayList<>(); - assertDoesNotThrow(() -> ServiceLoaderUtil.loadServices(BetterService.class, MethodHandles.lookup(), false) + ServiceLoaderUtil.safeStream( + BetterService.class, + ServiceLoader.load(BetterService.class, getClass().getClassLoader()), + LOGGER); + assertDoesNotThrow(() -> ServiceLoaderUtil.safeStream( + BetterService.class, + ServiceLoader.load(BetterService.class, getClass().getClassLoader()), + LOGGER) .forEach(services::add)); assertThat(services).hasSize(1); services.clear(); - assertDoesNotThrow(() -> ServiceLoaderUtil.loadServices(PropertySource.class, MethodHandles.lookup(), false) + assertDoesNotThrow(() -> ServiceLoaderUtil.safeStream( + PropertySource.class, + ServiceLoader.load(PropertySource.class, getClass().getClassLoader()), + LOGGER) .forEach(services::add)); assertThat(services).hasSize(3); } @@ -51,7 +65,10 @@ public class ServiceLoaderUtilTest { @UsingStatusListener public void testBrokenServiceFile(final ListStatusListener listener) { final List<Service> services = new ArrayList<>(); - assertDoesNotThrow(() -> ServiceLoaderUtil.loadServices(Service.class, MethodHandles.lookup(), false) + assertDoesNotThrow(() -> ServiceLoaderUtil.safeStream( + Service.class, + ServiceLoader.load(Service.class, getClass().getClassLoader()), + LOGGER) .forEach(services::add)); assertEquals(2, services.size()); // A warning for each broken service 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 18ed7befe4..4ddbdc5c5f 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 aQute.bnd.annotation.spi.ServiceConsumer; 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 @@ public class ThreadDumpMessage implements Message, StringBuilderFormattable { } 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/util/OsgiServiceLocator.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/OsgiServiceLocator.java index d061ccbd6d..46157290c1 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.apache.logging.log4j.status.StatusLogger; 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 class OsgiServiceLocator { public static <T> Stream<T> loadServices(final Class<T> 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 <T> Stream<T> loadServices(final Class<T> 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 daf9163203..310f432edd 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.Resolution; 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 @@ public final class PropertiesUtil { } 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 a669bf7143..c02526b4a0 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.Resolution; 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 @@ public final class ProviderUtil { 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 cf906eab69..30b56f83b5 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. + * <p> + * This class should be considered internal. + * </p> + * <p> + * 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}. + * </p> + * <p> + * The purpose of this class is to: + * </p> + * <ol> + * <li>skip faulty services, allowing for a partial retrieval of the good ones,</li> + * <li>allow to integrate other sources of services like OSGi services.</li> + * </ol> */ @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 <T> The service type. - * @param serviceType The class of the service. - * @param lookup The calling class data. - * @return A stream of service instances. - */ - public static <T> Stream<T> loadServices(final Class<T> 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 <T> 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} + * <p> + * It ignores the most common service loading errors. + * </p> + * @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 <T> Stream<T> loadServices(final Class<T> serviceType, final Lookup lookup, final boolean useTccl) { - return loadServices(serviceType, lookup, useTccl, true); - } - - static <T> Stream<T> loadServices( - final Class<T> serviceType, final Lookup lookup, final boolean useTccl, final boolean verbose) { - final ClassLoader classLoader = lookup.lookupClass().getClassLoader(); - Stream<T> 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<Class<?>> classes = new HashSet<>(); - // only the first occurrence of a class - return services.filter(service -> classes.add(service.getClass())); - } - - static <T> Stream<T> loadClassloaderServices( - final Class<T> serviceType, final Lookup lookup, final ClassLoader classLoader, final boolean verbose) { - return StreamSupport.stream(new ServiceLoaderSpliterator<T>(serviceType, lookup, classLoader, verbose), false); + public static <S> Stream<S> safeStream( + final Class<S> serviceType, final ServiceLoader<? extends S> serviceLoader, final Logger logger) { + requireNonNull(serviceLoader, "serviceLoader"); + final Collection<Class<?>> classes = new HashSet<>(); + final Stream<S> services = + StreamSupport.stream(new ServiceLoaderSpliterator<>(serviceType, serviceLoader, logger), false); + // Caller class may be null + final Class<?> callerClass = StackLocatorUtil.getCallerClass(2); + final Stream<S> 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 <T> Iterable<T> callServiceLoader( - final Lookup lookup, final Class<T> 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<ServiceLoader<T>> action = (PrivilegedAction<ServiceLoader<T>>) - callSite.getTarget() // - .bindTo(serviceType) - .bindTo(classLoader) - .invoke(); - final ServiceLoader<T> 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<T>) 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<S> implements Spliterator<S> { - - private final Iterator<S> serviceIterator; - private final Logger logger; + private static final class ServiceLoaderSpliterator<S> extends Spliterators.AbstractSpliterator<S> { private final String serviceName; + private final Iterator<? extends S> serviceIterator; + private final Logger logger; - public ServiceLoaderSpliterator( - final Class<S> 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<S> 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 final class ServiceLoaderUtil { 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<S> 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 bc20af0daf..27982ad4d9 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,9 @@ 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"); getCallerClassMethod = sunReflectionClass.getDeclaredMethod("getCallerClass", int.class); Object o = getCallerClassMethod.invoke(null, 0); getCallerClassMethod.invoke(null, 0); 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 c1299311ea..b610603b4b 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.SmtpManager; 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 final class SmtpAppender extends AbstractAppender { 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 24f34936e6..332b877a51 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 @@ package org.apache.logging.log4j.core.impl; 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 class ThreadContextDataInjector { private static List<ContextDataProvider> getServiceProviders() { final List<ContextDataProvider> 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 491c212f6f..1761498087 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.Cardinality; 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 class WatchManager extends AbstractLifeCycle { 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()); }
