为什么 log4j classes 由两个 class 加载程序加载?
Why are log4j classes loaded by two class loaders?
我有一个应用程序的 Maven 项目,我在 WildFly 服务器中 运行。该项目具有 log4j 依赖项:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.1</version>
</dependency>
我想像这样获取 LoggerContext:
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
但是,这会导致 ClassCastException:
class org.apache.logging.log4j.core.LoggerContext cannot be cast to class org.apache.logging.log4j.core.LoggerContext (org.apache.logging.log4j.core.LoggerContext is in unnamed module of loader 'deployment.WEB.war' @6e285ef6; org.apache.logging.log4j.core.LoggerContext is in unnamed module of loader 'deployment.WEB.war' @239cb91f)
经过一些调试,我发现问题是 class LoggerContext 是通过两个不同的 classloader 加载的。这怎么可能?起初,我以为这些依赖项会有两个不同的声明,但这可能不是那个问题。 (我已将版本更改为 2.17.0 并在两个 LoggerContext classes 上调用 class.getPackage().getSpecificationVersion()。对于两个 classes,版本已更改)。
class 被加载两次的原因可能是什么?
嗯,由于 Wildfly 中存在的 log4j 库,类 似乎被加载了两次。
如何避免这种情况:
向 WEB-INF 添加配置以从 wildfly 中排除日志库:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<exclude-subsystems>
<subsystem name="logging"/>
</exclude-subsystems>
<exclusions>
<module name="org.apache.commons.logging"/>
<module name="org.apache.log4j"/>
<module name="org.jboss.logging"/>
<module name="org.jboss.logging.jul-to-slf4j-stub"/>
<module name="org.jboss.logmanager"/>
<module name="org.jboss.logmanager.log4j"/>
<module name="org.slf4j"/>
<module name="org.slf4j.impl"/>
</exclusions>
</deployment>
</jboss-deployment-structure>
我有一个应用程序的 Maven 项目,我在 WildFly 服务器中 运行。该项目具有 log4j 依赖项:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.1</version>
</dependency>
我想像这样获取 LoggerContext:
LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
但是,这会导致 ClassCastException:
class org.apache.logging.log4j.core.LoggerContext cannot be cast to class org.apache.logging.log4j.core.LoggerContext (org.apache.logging.log4j.core.LoggerContext is in unnamed module of loader 'deployment.WEB.war' @6e285ef6; org.apache.logging.log4j.core.LoggerContext is in unnamed module of loader 'deployment.WEB.war' @239cb91f)
经过一些调试,我发现问题是 class LoggerContext 是通过两个不同的 classloader 加载的。这怎么可能?起初,我以为这些依赖项会有两个不同的声明,但这可能不是那个问题。 (我已将版本更改为 2.17.0 并在两个 LoggerContext classes 上调用 class.getPackage().getSpecificationVersion()。对于两个 classes,版本已更改)。
class 被加载两次的原因可能是什么?
嗯,由于 Wildfly 中存在的 log4j 库,类 似乎被加载了两次。
如何避免这种情况: 向 WEB-INF 添加配置以从 wildfly 中排除日志库:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
<deployment>
<exclude-subsystems>
<subsystem name="logging"/>
</exclude-subsystems>
<exclusions>
<module name="org.apache.commons.logging"/>
<module name="org.apache.log4j"/>
<module name="org.jboss.logging"/>
<module name="org.jboss.logging.jul-to-slf4j-stub"/>
<module name="org.jboss.logmanager"/>
<module name="org.jboss.logmanager.log4j"/>
<module name="org.slf4j"/>
<module name="org.slf4j.impl"/>
</exclusions>
</deployment>
</jboss-deployment-structure>