在 Hadoop 2.6.0 到 2.7.1 升级上启动 MRAppMaster 时出现 NoClassDefFoundError
NoClassDefFoundError when starting MRAppMaster on Hadoop 2.6.0 to 2.7.1 upgrade
将我们的应用程序从 2.6.0 更新到 2.7.1 后,我无法正确地获取我们的映射器作业 运行ning,作业日志中显示以下内容:
SEVERE: Error starting MRAppMaster
java.lang.NoClassDefFoundError: Could not initialize class org.apache.log4j.LogManager
at org.slf4j.impl.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:64)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:285)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:305)
at org.apache.hadoop.security.authentication.util.KerberosName.<clinit>(KerberosName.java:43)
at org.apache.hadoop.security.UserGroupInformation.initialize(UserGroupInformation.java:275)
at org.apache.hadoop.security.UserGroupInformation.setConfiguration(UserGroupInformation.java:311)
at org.apache.hadoop.mapreduce.v2.app.MRAppMaster.initAndStartAppMaster(MRAppMaster.java:1492)
at org.apache.hadoop.mapreduce.v2.app.MRAppMaster.main(MRAppMaster.java:1448)
我最初认为这是我们作业中的一个 class 路径问题,为此我们的库被复制到分布式缓存,然后在每个作业之前添加到作业的 class 路径工作 运行。尽管所有库都已就位并在作业 运行 之前添加到 class 路径,但经过一些验证确认。
hadoop classpath
和 yarn classpath
都显示 hadoop/share/hadoop
下的所有内容都在 class 路径上,其中包含 class 中的库 (log4j)问题属于上述。
我们有点没主意了。正在执行的代码在我们的 2.6.0 分支上运行良好。我们可能缺少什么?
我认为因为 Hadoop 版本 2.7.1 版本 drops support for JDK6 runtime and works with JDK 7+ only 您面临的问题可能是因为旧的 sl4j jar。您可以尝试将 sl4j.jar 更新到最新版本吗?
所以这最终成为一个微妙的问题,其中 class 问题 是 在 class 路径上提供的,但是当它最初被提供时加载它时爆炸,因为它引用了一个空变量,随后的 exception/stack 跟踪表明它丢失在 Hadoop 深处的某个地方!
在 Hadoop 2.7.x 中,ContainerLogAppender 获得了设置 ContainerLogFile 的能力。不幸的是,如果 log4j.appender.CLA.containerLogFile=${hadoop.root.logfile}
和 log4j.appender.CRLA.containerLogFile=${hadoop.root.logfile}
没有在 hadoop/etc/hadoop/container-log4j.properties
中设置,那么 NPE 就会爆炸。以前它默认为 "syslog",现在它没有默认值,很乐意让你自己挖个坑。因此,当 classes 在被 classloader 加载时爆炸时,它们实际上被删除了,因此为什么进一步向下工作报告 NoClassDefFoundError
而不是 ClassNotFoundException
.
将我们的应用程序从 2.6.0 更新到 2.7.1 后,我无法正确地获取我们的映射器作业 运行ning,作业日志中显示以下内容:
SEVERE: Error starting MRAppMaster
java.lang.NoClassDefFoundError: Could not initialize class org.apache.log4j.LogManager
at org.slf4j.impl.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:64)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:285)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:305)
at org.apache.hadoop.security.authentication.util.KerberosName.<clinit>(KerberosName.java:43)
at org.apache.hadoop.security.UserGroupInformation.initialize(UserGroupInformation.java:275)
at org.apache.hadoop.security.UserGroupInformation.setConfiguration(UserGroupInformation.java:311)
at org.apache.hadoop.mapreduce.v2.app.MRAppMaster.initAndStartAppMaster(MRAppMaster.java:1492)
at org.apache.hadoop.mapreduce.v2.app.MRAppMaster.main(MRAppMaster.java:1448)
我最初认为这是我们作业中的一个 class 路径问题,为此我们的库被复制到分布式缓存,然后在每个作业之前添加到作业的 class 路径工作 运行。尽管所有库都已就位并在作业 运行 之前添加到 class 路径,但经过一些验证确认。
hadoop classpath
和 yarn classpath
都显示 hadoop/share/hadoop
下的所有内容都在 class 路径上,其中包含 class 中的库 (log4j)问题属于上述。
我们有点没主意了。正在执行的代码在我们的 2.6.0 分支上运行良好。我们可能缺少什么?
我认为因为 Hadoop 版本 2.7.1 版本 drops support for JDK6 runtime and works with JDK 7+ only 您面临的问题可能是因为旧的 sl4j jar。您可以尝试将 sl4j.jar 更新到最新版本吗?
所以这最终成为一个微妙的问题,其中 class 问题 是 在 class 路径上提供的,但是当它最初被提供时加载它时爆炸,因为它引用了一个空变量,随后的 exception/stack 跟踪表明它丢失在 Hadoop 深处的某个地方!
在 Hadoop 2.7.x 中,ContainerLogAppender 获得了设置 ContainerLogFile 的能力。不幸的是,如果 log4j.appender.CLA.containerLogFile=${hadoop.root.logfile}
和 log4j.appender.CRLA.containerLogFile=${hadoop.root.logfile}
没有在 hadoop/etc/hadoop/container-log4j.properties
中设置,那么 NPE 就会爆炸。以前它默认为 "syslog",现在它没有默认值,很乐意让你自己挖个坑。因此,当 classes 在被 classloader 加载时爆炸时,它们实际上被删除了,因此为什么进一步向下工作报告 NoClassDefFoundError
而不是 ClassNotFoundException
.