Hello, I am trying to understand the way the context classloader and `ServiceLoader` are used in Log4j 2.x[1].
The `log4j-api` uses `LoaderUtil.getClassLoaders` in several places to lookup services from the context classloader and the `log4j-api` classloader. This procedure has IMHO some problems: 1. The services retrieved this way are assigned to static fields (except the call in `WatchEventService`): this causes a memory leak if `log4j-api` is in the server's classloader and the retrieved service in the web application classloader, 2. There is the small problem that if any service found by `ServiceLoader.load(Class, ClassLoader)` fails the `instanceof` check, all the others are thrown away. I solved it in `ServiceLoaderUtil`, 3. Probably this is not a problem, but I fail to understand why we look up services separately for a classloader and each of its ancestors. If the classloader implements the "delegate to parent" convention, we'll end up several instances of the same class. If the classloader is a webapp classloader and the service interface is in the webapp classloader, all services in the classloader ancestors will fail the 'instanceof' test. The only situation where this makes sense is if the service interface is in the server classloader (e.g. `javax.sql.DataSource`), then we can have two different services with the same class name. Is this the reason? 4. The following condition in `ThreadContextDataInjector` is pure magic for me: if (providers.stream().noneMatch(p -> p.getClass().isAssignableFrom(provider.getClass()))) { providers.add(provider); } As I understand it, if we have a base class, we don't want its derived classes? I have don't some refactoring of the ServiceLoader code in: https://github.com/apache/logging-log4j2/pull/804 [1] https://issues.apache.org/jira/browse/LOG4J2-3427