Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Level

本文详细解析了在运行Hadoop WordCount程序时遇到的NoClassDefFoundError异常,通过调整log4j依赖版本从1.2.17到1.2.14成功解决了问题。

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Level
    at org.apache.hadoop.mapred.JobConf.<clinit>(JobConf.java:357)
    at org.apache.hadoop.mapreduce.Job.getInstance(Job.java:186)
    at org.apache.hadoop.mapreduce.Job.getInstance(Job.java:206)
    at com.hadoop.hadoop_test.WordCount.main(WordCount.java:52)
Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Level
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 4 more
在统计wordcount时,报一下错误,仔细分析了一下:

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

把log4j改1.2.14版本,错误消失。

<think>我们正在处理用户将log4j.properties迁移到log4j2.xml后出现的NoClassDefFoundError: org/apache/logging/log4j/util/Lazy 异常。 这个异常通常是由于log4j2的依赖不完整或版本冲突引起的。特别是,Lazy类属于log4j-core的内部工具类,如果log4j-api和log4j-core版本不匹配,或者缺少必要的依赖,就可能出现此问题。 根据用户提供的配置文件转换,我们已经生成了log4j2.xml,但用户可能没有正确更新依赖。 解决方案步骤: 1. 确保使用正确的Log4j2版本(安全版本,如2.23.1)。 2. 检查依赖树,确保没有混合使用Log4j1.x和Log4j2.x的依赖。 3. 确保所有Log4j2相关的依赖版本一致。 具体操作: 第一步:更新Maven依赖(如果使用Maven) 在pom.xml中,确保有以下依赖,并且版本一致(这里以2.23.1为例,这是当前的安全版本): ```xml <dependencies> <!-- Log4j2 API --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.23.1</version> </dependency> <!-- Log4j2 Core --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.23.1</version> </dependency> <!-- 如果使用SLF4J桥接 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j2-impl</artifactId> <version>2.23.1</version> <scope>runtime</scope> </dependency> </dependencies> ``` 第二步:检查并移除冲突的依赖 使用Maven命令检查依赖树: ```bash mvn dependency:tree ``` 查找是否有旧版本的log4j-core或log4j-api,以及是否有log4j1.x的依赖(如log4j:log4j)和旧版的slf4j-log4j12。如果有,需要排除或删除。 例如,如果发现slf4j-log4j12,移除它: ```xml <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.30</version> <scope>compile</scope> </dependency> ``` 第三步:清理和重新构建项目 清理项目并重新构建,确保所有依赖被正确下载。 如果问题仍然存在,可能是因为类加载器问题(例如在Web容器中),尝试检查类路径是否包含多个版本的log4j2。 第四步:检查配置文件位置 确保log4j2.xml位于类路径的根目录(如src/main/resources)。 第五步:如果使用SLF4J,确保桥接器正确 使用SLF4J时,应该通过SLF4J获取Logger,并且使用log4j-slf4j2-impl桥接。 示例代码: ```java import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MyClass { private static final Logger logger = LoggerFactory.getLogger(MyClass.class); } ``` 如果以上步骤都正确,通常可以解决NoClassDefFoundError。 如果用户仍然遇到问题,建议提供完整的异常堆栈和依赖树以进一步分析。 相关问题: 1. 如何解决Log4j2迁移后出现的类冲突问题? 2. 在Maven中如何排除传递依赖? 3. Log4j2的SLF4J桥接器应该如何配置? 4. 如何验证Log4j2配置是否正确加载?</think>### 解决 Log4j2 迁移后的 `NoClassDefFoundError: org/apache/logging/log4j/util/Lazy` 异常 此问题通常由 **依赖冲突** 或 **版本不兼容** 引起。以下是完整的解决步骤: --- ### 1. **检查依赖冲突(关键步骤)** #### Maven 项目检查命令: ```bash mvn dependency:tree -Dincludes=log4j ``` 重点关注输出中是否存在: - 多个不同版本的 `log4j-core` 或 `log4j-api` - 残留的 Log4j 1.x 依赖(如 `log4j:log4j`) - 冲突的桥接器(如 `slf4j-log4j12`) #### 解决方案: ```xml <!-- 移除冲突依赖 --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> <scope>provided</scope> <!-- 完全移除或标记为 provided --> </dependency> <!-- 统一 Log4j2 版本 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.23.1</version> <!-- 必须与 log4j-api 同版本 --> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> <version>2.23.1</version> </dependency> ``` --- ### 2. **验证桥接器配置** 确保使用正确的 SLF4J 桥接器: ```xml <!-- 正确配置 --> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-slf4j2-impl</artifactId> <!-- 注意是2-impl --> <version>2.23.1</version> </dependency> <!-- 移除错误的桥接器 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <!-- 冲突源!必须移除 --> <version>1.7.36</version> <scope>provided</scope> </dependency> ``` --- ### 3. **检查类加载顺序(Web 服务器场景)** 在 Tomcat/Jetty 等容器中: 1. 检查 `WEB-INF/lib` 是否包含多个 log4j2 版本 2. 在 `WEB-INF/web.xml` 添加优先加载项: ```xml <context-param> <param-name>log4jContextName</param-name> <param-value>MyWebApp</param-value> </context-param> <context-param> <param-name>isLog4jAutoInitializationDisabled</param-name> <param-value>true</param-value> <!-- 禁用容器自动初始化 --> </context-param> ``` --- ### 4. **验证配置文件加载** 在代码中显式检查配置: ```java import org.apache.logging.log4j.core.config.Configurator; public class LogInit { public static void init() { Configurator.initialize( null, "classpath:log4j2.xml" // 确认路径正确 ); System.out.println("Log4j2 initialized: " + org.apache.logging.log4j.LogManager.getContext(false).hasLogger("ROOT") ); } } ``` --- ### 5. **依赖树冲突示例分析 常见冲突模式: ``` [INFO] +- org.springframework.boot:spring-boot-starter-log4j2:jar:3.2.0 [INFO] | +- org.apache.logging.log4j:log4j-core:jar:2.22.1 [INFO] | \- org.apache.logging.log4j:log4j-api:jar:2.22.1 [INFO] \- com.datastax.oss:java-driver-core:jar:4.17.0 [INFO] \- org.apache.logging.log4j:log4j-core:jar:2.20.0 <!-- 冲突版本! --> ``` 解决方案: ```xml <dependency> <groupId>com.datastax.oss</groupId> <artifactId>java-driver-core</artifactId> <version>4.17.0</version> <exclusions> <exclusion> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <!-- 排除传递依赖 --> </exclusion> </exclusions> </dependency> ``` --- ### 根本原因说明 `Lazy` 类是 Log4j2 内部工具类,位于 `log4j-core-2.x.jar` 中。当出现: 1. **版本分裂**:`log4j-api` 与 `log4j-core` 版本不一致 2. **类加载污染**:服务器容器预载了旧版本 3. **依赖冲突**:Maven/Gradle 依赖解析顺序错误 时,会导致 JVM 加载到不完整的类定义,从而引发 `NoClassDefFoundError`[^1]。 [^1]: 详见 Apache Log4j 官方文档 [Class Loading Issues](https://logging.apache.org/log4j/2.x/faq.html#which_jars)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DisFney

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值