You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hadoop MapReduce作业出现OptionConverter.convertLevel间歇性错误求助

MapReduce间歇性NoSuchMethodError问题(log4j版本冲突)

错误详情

执行MapReduce作业时出现间歇性错误,报错信息:

2022-12-28 01:20:53,882 ERROR [main] org.apache.hadoop.mapred.YarnChild: Error running child : java.lang.NoSuchMethodError: org/apache/log4j/helpers/OptionConverter.convertLevel(Ljava/lang/String;Lorg/apache/logging/log4j/Level;)Lorg/apache/logging/log4j/Level; (loaded from file:/opt/hadoop-3.3.0/share/hadoop/common/lib/log4j-1.2.17.jar by sun.misc.Launcher$AppClassLoader@350ed555) called from class org.apache.log4j.config.PropertiesConfiguration (loaded from file:/data/hadoop/yarn/usercache/hdfs-user/appcache/application_1671477750397_6197/filecache/10/job.jar/job.jar by sun.misc.Launcher$AppClassLoader@350ed555).

错误随机出现:有时导致Mapper失败,有时作业能正常完成。项目Gradle配置如下:

plugins {
    id 'java'
    id "com.github.davidmc24.gradle.plugin.avro" version "1.3.0"
}
dependencies {
    compileOnly group: 'org.apache.hadoop', name: 'hadoop-client', version: '3.3.0'
    implementation group: 'org.apache.avro', name: 'avro', version: '1.8.1'
    implementation group: 'org.apache.avro', name: 'avro-mapred', version: '1.10.2'
    implementation group: 'io.netty', name: 'netty-buffer', version: '4.1.51.Final'
    implementation  group: 'joda-time', name: 'joda-time', version:'2.8.1'
    implementation group: 'org.javatuples', name: 'javatuples', version: '1.2'
    implementation group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-yaml', version: '2.12.4'
    testImplementation group: 'junit', name: 'junit', version: "$junit4Version"
    implementation project(':libraries:java-dcl')
    implementation project(':libraries:sdp')

    testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.6.1'
}

generateAvroJava {
    source("${projectDir}/src/main/avro")//sourcepath avrofile
}

// The alternative to below is to put all java that is dependent on scala (or on the java dependent on the scala) in the src/main/scala dir
// https://stackoverflow.com/questions/23261075/compiling-scala-before-alongside-java-with-gradle
sourceSets {
    main {
        java {
            srcDirs = ['src/main/java']
        }
    }
}

问题根源

这是典型的log4j版本冲突:

  • Hadoop 3.3.0内置log4j 1.2.17,该版本的OptionConverter类没有convertLevel(String, org.apache.logging.log4j.Level)方法。
  • 作业jar中包含了高版本log4j相关组件(大概率来自avro-mapred依赖),其中PropertiesConfiguration类调用了这个不存在的方法。
  • 类加载顺序的随机性导致间歇性报错:当集群先加载Hadoop的旧log4j时触发错误;若先加载作业jar中的组件,且未执行到该方法调用,作业就能正常运行。

解决办法

1. 排除依赖中的冲突log4j包

修改Gradle依赖,排除avro等依赖引入的log4j相关组件,确保作业使用集群自带的版本:

dependencies {
    // 保留原有依赖,对avro-mapred添加排除规则
    implementation('org.apache.avro:avro-mapred:1.10.2') {
        exclude group: 'org.apache.logging.log4j'
        exclude group: 'log4j'
    }
    // 其他可能引入log4j的依赖也做同样处理
}

2. 强制统一log4j版本

在Gradle中强制指定与Hadoop兼容的log4j版本,覆盖所有依赖的版本:

configurations.all {
    resolutionStrategy {
        force 'log4j:log4j:1.2.17'
        // 若需log4j2 API,指定Hadoop兼容的版本
        force 'org.apache.logging.log4j:log4j-api:2.17.1'
    }
}

3. 调整打包策略

确保作业jar中不包含log4j相关文件:

  • 执行gradle dependencies查看依赖树,确认无多余log4j包被引入。
  • 若使用打包插件(如shadowJar),添加规则排除log4j的jar和类文件。

4. 使用桥接包(可选)

如果代码需要log4j 2.x特性,引入log4j 1.x到2.x的桥接包,并设置为compileOnly避免打包到作业jar:

dependencies {
    compileOnly 'org.apache.logging.log4j:log4j-1.2-api:2.17.1'
}

内容的提问来源于stack exchange,提问作者Sitakant Mishra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 16:25:35