来自 org.apache.hadoop.mapreduce.lib.input.FileInputFormat.listStatus 的番石榴秒表 IllegalAccessError

IllegalAccessError to guava's StopWatch from org.apache.hadoop.mapreduce.lib.input.FileInputFormat.listStatus

我正在尝试 运行 小型 spark 应用程序,但遇到以下异常:

Exception in thread "main" java.lang.IllegalAccessError: tried to access method com.google.common.base.Stopwatch.<init>()V from class org.apache.hadoop.mapreduce.lib.input.FileInputFormat
    at org.apache.hadoop.mapreduce.lib.input.FileInputFormat.listStatus(FileInputFormat.java:262)
    at org.apache.hadoop.mapreduce.lib.input.CombineFileInputFormat.getSplits(CombineFileInputFormat.java:217)
    at org.apache.spark.rdd.NewHadoopRDD.getPartitions(NewHadoopRDD.scala:95)
    at org.apache.spark.rdd.RDD$$anonfun$partitions.apply(RDD.scala:219)
    at org.apache.spark.rdd.RDD$$anonfun$partitions.apply(RDD.scala:217)
    at scala.Option.getOrElse(Option.scala:120)
    at org.apache.spark.rdd.RDD.partitions(RDD.scala:217)
    at org.apache.spark.rdd.MapPartitionsRDD.getPartitions(MapPartitionsRDD.scala:32)
    at org.apache.spark.rdd.RDD$$anonfun$partitions.apply(RDD.scala:219)
    at org.apache.spark.rdd.RDD$$anonfun$partitions.apply(RDD.scala:217)
    at scala.Option.getOrElse(Option.scala:120)

相关的 gradle 依赖项部分:

compile('org.apache.spark:spark-core_2.10:1.3.1')
compile('org.apache.hadoop:hadoop-mapreduce-client-core:2.6.2') {force = true}
compile('org.apache.hadoop:hadoop-mapreduce-client-app:2.6.2') {force = true}
compile('org.apache.hadoop:hadoop-mapreduce-client-shuffle:2.6.2') {force = true}
compile('com.google.guava:guava:19.0') { force = true }

听起来你的 Guava 版本不匹配。

您的代码库中的某些内容正在尝试调用 Stopwatch 构造函数,但该构造函数已从 Guava 17.0 中删除,取而代之的是静态工厂方法(createStarted()createUnstarted())在 Guava 15.0 中添加。

您应该更新任何试图使用构造函数的代码,改为使用静态工厂方法。

hadoop:hadoop-mapreduce-client-core

版本 2.6.2 不能与 guava 的新版本一起使用(我试过 17.0 - 19.0)因为 guavaStopWatch 构造函数无法访问(导致上述 IllegalAccessError

使用 hadoop-mapreduce-client-core 的最新版本 - 2.7.2(他们在上述方法中不使用 guavaStopWatch,而是使用 org.apache.hadoop.util.StopWatch) 解决了这个问题,需要两个额外的依赖项:

compile('org.apache.hadoop:hadoop-mapreduce-client-core:2.7.2') {force = true}

compile('org.apache.hadoop:hadoop-common:2.7.2') {force = true} // required for org.apache.hadoop.util.StopWatch  

compile('commons-io:commons-io:2.4') {force = true} // required for org.apache.commons.io.Charsets that is used internally

注意: 有两个 org.apache.commons.io 包: commons-io:commons-io(我们这里的),和 org.apache.commons:commons-io(旧的,2007 年)。确保包括正确的。

我在使用 Spark 1.6.1 时遇到了这个问题,因为我们的一个附加依赖项驱逐了 Guava 14.0.1 并将其替换为 18.0。 Spark 对 hadoop-client 的基本依赖为 2.2。请参阅 [Maven 回购] (https://mvnrepository.com/artifact/org.apache.spark/spark-core_2.10/1.6.1)

有效的解决方案是向 sbt libraryDependencies 添加以下内容:"org.apache.hadoop" % "hadoop-client" % "2.7.2"

在我的例子中,因为添加guava 21.0导致错误。

 <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>21.0</version>
 </dependency>

之后,我正在使用 guava 15.0 或删除上述依赖项。我的代码运行良好。

我刚刚将我的 guava 版本从 19.0 更改为 15.0,它可以正常工作。我目前使用的版本是 spark 2.2

<dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>15.0</version>
      </dependency>

看来是依赖库的问题

基本上,当您尝试将数据放入 hbase 时会遇到问题 table。

最初我用过<dependency> <groupId>org.apache.hbase</groupId> <artifactId>hbase-client</artifactId> <version>1.1.2</version> </dependency>

我遇到了和你类似的问题,后来我改成<dependency> <groupId>org.apache.hbase</groupId> <artifactId>hbase-shaded-client</artifactId> <version>1.1.2</version> </dependency>,现在问题已经解决了。

解决方案

  1. guava.jar 文件的多个版本作为传递依赖项发生冲突,导致此异常。
  2. 确定冲突版本并在 pom.xml 中添加为排除项将解决此问题。
  3. 在我的例子中,添加 pmml-evaluator version 1.4.1 依赖导致了这个异常。
  4. 通过依赖层次结构识别并添加 Maven 排除解决了这个问题。

       <dependency>
        <groupId>org.jpmml</groupId>
        <artifactId>pmml-evaluator</artifactId>
        <version>1.4.1</version>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
            </exclusion>
        </exclusions>
       </dependency>
    

如果您想在不重新构建 Spark 的情况下解决此问题,例如使用预构建的 Spark 发行版,那么我发现以下内容适用于 Apache Spark 2.3.0(即使用预构建的:'spark-2.3.0-bin-without-hadoop'):

  1. 从 Spark 'jars' 目录重命名或删除 'hadoop-mapreduce-client-core' jar 文件的错误版本(在我的例子中是 'hadoop-mapreduce-client-core-2.6.5.jar')。
  2. 将 'hadoop-mapreduce-client-core' jar 的兼容版本(从您的 Hadoop 安装)复制(或软 link)到 Spark 'jars' 目录中。

也可以通过更改类路径强制使用所需的 'hadoop-mapreduce-client-core' jar 文件(以便 Spark 从 Hadoop 中找到版本,而不是随 Spark 分发的版本)。

我们刚刚使用 IntelliJ 和 Spark 遇到了同样的情况。

使用时

libraryDependencies += "org.apache.spark" %% "spark-core" % "2.3.1"
libraryDependencies += "org.apache.spark" %% "spark-sql" % "2.3.1"

com.google.guava下载20.0,下载hadoop client 2.6.5。

最快的解决方案是将 guava 库强制升级到版本 15.0 (SBT)

dependencyOverrides += "com.google.guava" % "guava" % "15.0"