执行spark-shell时出现NoClassDefFoundError com.apache.hadoop.fs.FSDataInputStream。

41

我已经下载了不带Hadoop的Spark 1.4.0预编译版本(使用用户提供的Hadoop)。当我运行spark-shell命令时,出现了以下错误:

> Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/hadoop/fs/
FSDataInputStream
        at org.apache.spark.deploy.SparkSubmitArguments$$anonfun$mergeDefaultSpa
rkProperties$1.apply(SparkSubmitArguments.scala:111)
        at org.apache.spark.deploy.SparkSubmitArguments$$anonfun$mergeDefaultSpa
rkProperties$1.apply(SparkSubmitArguments.scala:111)
        at scala.Option.getOrElse(Option.scala:120)
        at org.apache.spark.deploy.SparkSubmitArguments.mergeDefaultSparkPropert
ies(SparkSubmitArguments.scala:111)
        at org.apache.spark.deploy.SparkSubmitArguments.<init>(SparkSubmitArgume
nts.scala:97)
        at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:106)
        at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
Caused by: java.lang.ClassNotFoundException: org.apache.hadoop.fs.FSDataInputStr
eam
        at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
        ... 7 more

我在网上搜索了一下,说是 spark-env.cmd 中还没有设置 HADOOP_HOME。但是在 Spark 安装文件夹中找不到 spark-env.cmd。

我追踪了 spark-shell 命令,似乎里面没有 HADOOP_CONFIG。我尝试将 HADOOP_HOME 添加到环境变量中,但仍然出现相同的异常。

实际上我并没有真正使用 hadoop。我按照这个问题的建议下载了 hadoop 作为解决方法。

我使用的是 Windows 8 和 Scala 2.10。

任何帮助都将不胜感激。谢谢。


我曾经遇到过同样的问题,后来我安装了hadoop-2版本,现在它可以正常工作了。 - Chitrasen
17个回答

46
“Spark的构建名称中的“without Hadoop”是误导性的:它意味着该构建不与特定的Hadoop发行版绑定,而不是指该构建旨在在没有Hadoop的情况下运行:用户应指示在哪里找到Hadoop(请参见https://spark.apache.org/docs/latest/hadoop-provided.html)”
“解决此问题的一种简洁方法是:”
  1. 获取Hadoop Windows二进制文件。最好进行构建,但这很痛苦(有一些提示请参见:Hadoop on Windows Building/ Installation Error)。否则可以通过谷歌搜索获得,例如目前你可以从这里下载2.6.0版本:http://www.barik.net/archive/2015/01/19/172716/
  2. 创建一个类似于下面的spark-env.cmd文件(修改Hadoop路径以匹配您的安装): @echo off set HADOOP_HOME=D:\Utils\hadoop-2.7.1 set PATH=%HADOOP_HOME%\bin;%PATH% set SPARK_DIST_CLASSPATH=<在此处粘贴%HADOOP_HOME%\bin\hadoop classpath的输出>
  3. 将此spark-env.cmd文件放置在与Spark基础文件夹位于同一级别的conf文件夹中(可能看起来很奇怪),或者放置在由SPARK_CONF_DIR环境变量指示的文件夹中。

我理解我的问题,但我有一个问题:在Windows cmd文件中是否可以像在Linux bash文件中一样调用$(hadoop classpath)? - Ray
@Ray,很抱歉我无法提供专业的帮助,但我可以说上述方法对我有效。我相信有一种方法可以在spark-env.cmd中自动调用“hadoop classpath”,以避免手动复制/粘贴,但我没有深入研究过。祝你好运! - tiho
应该可以工作,类路径在这里定义:https://github.com/apache/spark/blob/284e29a870bbb62f59988a5d88cd12f1b0b6f9d3/launcher/src/main/java/org/apache/spark/launcher/AbstractCommandBuilder.java#L213 - Thomas Decaux

21

我也遇到了这个问题,

export SPARK_DIST_CLASSPATH=`hadoop classpath`

问题已解决。


2
完全有帮助 - Turbero

21

我也遇到了同样的问题,在Spark的入门页面上其实已经提到如何处理这个问题:

### in conf/spark-env.sh ###

# If 'hadoop' binary is on your PATH
export SPARK_DIST_CLASSPATH=$(hadoop classpath)

# With explicit path to 'hadoop' binary
export SPARK_DIST_CLASSPATH=$(/path/to/hadoop/bin/hadoop classpath)

# Passing a Hadoop configuration directory
export SPARK_DIST_CLASSPATH=$(hadoop --config /path/to/configs classpath)

如果你想使用自己的hadoop,请遵循以下3个选项之一,将其复制并粘贴到spark-env.sh文件中:

1- 如果你的PATH环境变量中已经有了hadoop

2- 如果你想显式地指定hadoop二进制文件

3- 你还可以显示hadoop配置文件夹

http://spark.apache.org/docs/latest/hadoop-provided.html


5

我在尝试熟悉Spark时遇到了相同的错误。我理解这个错误信息是,虽然Spark不需要Hadoop集群来运行,但它确实需要一些Hadoop类。由于我只是在玩弄Spark,并且不关心使用哪个版本的Hadoop库,因此我只下载了一个预先构建好的带有Hadoop版本(2.6)的Spark二进制文件,事情开始正常运作。


5

linux

ENV SPARK_DIST_CLASSPATH="$HADOOP_HOME/etc/hadoop/*:$HADOOP_HOME/share/hadoop/common/lib/*:$HADOOP_HOME/share/hadoop/common/*:$HADOOP_HOME/share/hadoop/hdfs/*:$HADOOP_HOME/share/hadoop/hdfs/lib/*:$HADOOP_HOME/share/hadoop/hdfs/*:$HADOOP_HOME/share/hadoop/yarn/lib/*:$HADOOP_HOME/share/hadoop/yarn/*:$HADOOP_HOME/share/hadoop/mapreduce/lib/*:$HADOOP_HOME/share/hadoop/mapreduce/*:$HADOOP_HOME/share/hadoop/tools/lib/*"

windows

set SPARK_DIST_CLASSPATH=%HADOOP_HOME%\etc\hadoop\*;%HADOOP_HOME%\share\hadoop\common\lib\*;%HADOOP_HOME%\share\hadoop\common\*;%HADOOP_HOME%\share\hadoop\hdfs\*;%HADOOP_HOME%\share\hadoop\hdfs\lib\*;%HADOOP_HOME%\share\hadoop\hdfs\*;%HADOOP_HOME%\share\hadoop\yarn\lib\*;%HADOOP_HOME%\share\hadoop\yarn\*;%HADOOP_HOME%\share\hadoop\mapreduce\lib\*;%HADOOP_HOME%\share\hadoop\mapreduce\*;%HADOOP_HOME%\share\hadoop\tools\lib\*

4

进入SPARK_HOME -> conf目录

复制spark-env.sh.template文件并将其重命名为spark-env.sh。在此文件中,您可以设置Spark的参数。


感谢您的回复。您有什么想法,我应该修改哪个变量?我已将它重命名为spark-env.cmd,因为我正在使用Windows,并添加了“set HADOOP_CONF_DIR=*path”,但它仍然产生相同的异常。 - David
首先,尝试在spark-env.cmd中设置HADOOP_HOME并重新运行它,但如果仍然出现相同的问题,则在相同的配置文件中将hadoop-common jar文件导出到spark classpath中。 - Kshitij Kulshrestha
我已经设置了HADOOP_HOME,并将hadoop-common.jar复制到lib和conf文件夹中...但仍然没有运气:( - David
不要仅仅复制他们的类路径 - 例如: export SPARK_CLASSPATH=$SPARK_CLASSPATH:hadoop-common.jar - Kshitij Kulshrestha

3
在运行spark-submit之前,从您的包目录中运行以下命令-
export SPARK_DIST_CLASSPATH=`hadoop classpath`

1

你的代码中应该添加这些JAR文件:

  1. common-cli-1.2.jar
  2. hadoop-common-2.7.2.jar

1
我终于找到了移除异常的解决方案。 在spark-class2.cmd中添加以下内容:
set HADOOP_CLASS1=%HADOOP_HOME%\share\hadoop\common\*
set HADOOP_CLASS2=%HADOOP_HOME%\share\hadoop\common\lib\*
set HADOOP_CLASS3=%HADOOP_HOME%\share\hadoop\mapreduce\*
set HADOOP_CLASS4=%HADOOP_HOME%\share\hadoop\mapreduce\lib\*
set HADOOP_CLASS5=%HADOOP_HOME%\share\hadoop\yarn\*
set HADOOP_CLASS6=%HADOOP_HOME%\share\hadoop\yarn\lib\*
set HADOOP_CLASS7=%HADOOP_HOME%\share\hadoop\hdfs\*
set HADOOP_CLASS8=%HADOOP_HOME%\share\hadoop\hdfs\lib\*

set CLASSPATH=%HADOOP_CLASS1%;%HADOOP_CLASS2%;%HADOOP_CLASS3%;%HADOOP_CLASS4%;%HADOOP_CLASS5%;%HADOOP_CLASS6%;%HADOOP_CLASS7%;%HADOOP_CLASS8%;%LAUNCH_CLASSPATH%

然后,将以下内容更改为:
"%RUNNER%" -cp %CLASSPATH%;%LAUNCH_CLASSPATH% org.apache.spark.launcher.Main %* > %LAUNCHER_OUTPUT%

收件人:

"%RUNNER%" -Dhadoop.home.dir=*hadoop-installation-folder* -cp %CLASSPATH% %JAVA_OPTS% %*

这对我来说很好用,但我不确定这是否是最佳解决方案。


0

对于我的情况

在本地运行Spark作业与在集群上运行有所不同。在集群上,您可能需要遵循不同的依赖关系/上下文。因此,在您的pom.xml中,您可能已经声明了一些依赖项为provided

当在本地运行时,您不需要这些provided依赖项。只需将其注释掉并重新构建即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接