Description
I have tried to upgrade my tests from SLF4J 1.7.36 to SLF4J 2.0.3, but they are failing with this error:
{{java.util.ServiceConfigurationError: org.slf4j.spi.SLF4JServiceProvider: org.slf4j.simple.SimpleServiceProvider not a subtype at java.base/java.util.ServiceLoader.fail(ServiceLoader.java:589) at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(ServiceLoader.java:1237) at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(ServiceLoader.java:1265) at java.base/java.util.ServiceLoader$2.hasNext(ServiceLoader.java:1300) at java.base/java.util.ServiceLoader$3.hasNext(ServiceLoader.java:1385) at org.slf4j.LoggerFactory.findServiceProviders(LoggerFactory.java:104) at org.slf4j.LoggerFactory.bind(LoggerFactory.java:147) at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:139) at org.slf4j.LoggerFactory.getProvider(LoggerFactory.java:422) at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:408) at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:357) at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:383) }}
My test has added slf4j-api, slf4j-simple and a jar containing a Callable into a single classloader that has a null parent classloader, and is then executing the task isolated from the application classloader. But unfortunately for me, LoggerFactory.findServiceProviders() is implemented like this:
private static List<SLF4JServiceProvider> findServiceProviders() {
ServiceLoader<SLF4JServiceProvider> serviceLoader = ServiceLoader.load(SLF4JServiceProvider.class);
List<SLF4JServiceProvider> providerList = new ArrayList<>();
for (SLF4JServiceProvider provider : serviceLoader) {
providerList.add(provider);
}
return providerList;
}
Specifically, ServiceLoader.load() does not specify which classloader to use, and so defaults to the ThreadContextClassLoader.
I believe a more compatible (with earlier versions of SLF4J) choice would be:
ServiceLoader.load(SLF4JServiceProvider.class, LoggerFactory.class.getClassLoader())