🛠️ 解决 Log4j 1.x 与 Log4j 2 冲突导致的 IncompatibleClassChangeError 完整方案

适用环境:Hadoop 3.4.2 + Hive 4.1(或其他使用 SLF4J + Log4j 2 的大数据组件)
错误特征

java.lang.IncompatibleClassChangeError: 
class org.apache.log4j.bridge.LogEventAdapter overrides final method 
org.apache.log4j.spi.LoggingEvent.getProperty(...)

🔍 问题根源


该错误是由于 Log4j 1.x(或其社区维护版 Reload4j)与 Log4j 2 同时存在于 classpath 中 导致的 JVM 类加载冲突:

  • reload4j-*.jar 或 log4j-1.2*.jar 提供了 org.apache.log4j.spi.LoggingEvent,其中 getProperty() 方法被声明为 final
  • Log4j 2 的兼容桥接包 log4j-1.2-api-*.jar 尝试通过 LogEventAdapter 重写该 final 方法
  • JVM 在类验证阶段拒绝此操作 → 抛出 IncompatibleClassChangeError → 容器退出(exitCode=1)。

💡 即使你的代码未直接使用 Log4j 1 API,只要这些 JAR 存在,就会触发冲突!


✅ 完整解决步骤

第一步:清理 Hadoop 中的 Log4j 1.x / Reload4j

# 进入 Hadoop common lib 目录
cd /data/hadoop/share/hadoop/common/lib/

# 移除 Reload4j(核心冲突源)
mv reload4j-1.2.22.jar reload4j-1.2.22.jar.bak

确认无其他 Log4j 1.x JAR
ls -l | grep -iE 'log4j|reload'
# 应无有效 JAR 输出(.bak 备份文件可忽略)

⚠️ 关键reload4j-*.jar 是 Log4j 1.x 的完整实现,必须移除!


第二步:清理 Hive 中的 Log4j 1.x 桥接包

# 进入 Hive lib 目录
cd $HIVE_HOME/lib

#  Log4j 1.x API 桥接包(Hive 4.1 不需要)
mv  log4j-1.2-api-2.24.3.jar log4j-1.2-api-2.24.3.jar.bak

# 验证保留的 JAR(应仅包含 Log4j 2)
ls -l | grep log4j

Hive lib 正确内容

log4j-api-2.24.3.jar
log4j-core-2.24.3.jar
log4j-slf4j-impl-2.24.3.jar
log4j-web-2.24.3.jar   # 可选,用于 Web UI

绝对禁止存在

  • log4j-1.2-api-*.jar
  • log4j-1.2*.jar
  • reload4j-*.jar
  • slf4j-log4j12-*.jar

第三步:检查配置是否引入额外 JAR

1. 检查 hive-site.xml
<!-- 确保 hive.aux.jars.path 不包含旧日志 JAR -->
<property>
  <name>hive.aux.jars.path</name>
  <value></value> <!-- 应为空或不含 log4j/reload4j 路径 -->
</property>
2. 检查环境变量
echo $HADOOP_CLASSPATH
echo $CLASSPATH
# 确保不包含 /path/to/log4j-1.2.jar 等路径

第四步:【必须】重启整个集群

YARN NodeManager 会在启动时缓存 classpath,不重启无法清除旧 JAR!

# 1. 停止 HiveServer2
pkill -f HiveServer2

# 2. 停止 YARN 和 HDFS
$HADOOP_HOME/sbin/stop-yarn.sh
$HADOOP_HOME/sbin/stop-dfs.sh

# 3. 确认无残留进程
jps
# 输出应只有:Jps

# 4. 启动 HDFS
$HADOOP_HOME/sbin/start-dfs.sh

# 5. 启动 YARN
$HADOOP_HOME/sbin/start-yarn.sh

# 6. 启动 HiveServer2
nohup $HIVE_HOME/bin/hive --service hiveserver2 > /tmp/hive.log 2>&1 &

第五步:验证修复结果

方法 1:运行简单 Hive 查询
SET hive.execution.engine=mr;
SELECT current_database();

✅ 成功返回 default → 修复成功。

方法 2:运行纯 MapReduce 任务(绕过 Hive)
hadoop jar /data/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar pi 2 10

✅ 成功完成 → 说明 Hadoop 本身已干净。


📌 最佳实践建议

项目推荐做法
日志实现统一使用 Log4j 2.17+
Hadoop移除所有 log4j-1.2*reload4j*slf4j-reload4j*
Hive 4.1仅保留 log4j-apilog4j-corelog4j-slf4j-impl
配置文件在 $HADOOP_HOME/etc/hadoop/ 放置 log4j2.xml
升级策略避免混用不同版本日志框架

更多推荐