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

Spark连接BigQuery触发java.lang.NoSuchMethodError异常求助

我之前在Spark 2.3.x环境下用BigQuery Connector时也踩过这个坑!这个NoSuchMethodError的本质不是你打包的fat jar里有Guava版本冲突,而是Spark 2.3.x默认自带的Guava版本太低(14.0.1左右),而你用的spark-bigquery 0.18.0依赖的Guava 30.0-jre才有com.google.common.base.Optional.toJavaUtil()这个方法——关键是Spark运行时会优先加载自身classpath里的旧Guava,哪怕你的jar里已经打包了高版本也没用。

下面给你两个可行的解决方案,覆盖快速测试到生产环境场景:

方案1:本地模式快速验证——强制优先加载你的jar类

如果只是本地测试,可以通过spark-submit的参数让driver优先使用你fat jar里的类,跳过Spark自带的旧Guava:

spark-submit \
  --deploy-mode client \
  --conf spark.driver.userClassPathFirst=true \
  --class com.bigquery.OwnDataSetReader \
  BigQueryConnector.jar

或者直接指定driver的classpath,把你的jar放在最前面:

spark-submit \
  --deploy-mode client \
  --driver-class-path BigQueryConnector.jar \
  --class com.bigquery.OwnDataSetReader \
  BigQueryConnector.jar

⚠️ 注意:spark.driver.userClassPathFirst=true可能会引发其他依赖冲突(比如Spark自带的其他库和你jar里的版本不兼容),所以这个方法只适合本地快速验证,生产环境不推荐。

方案2:生产环境推荐——用SBT Shade重命名Guava包

最稳妥的方法是在打包时把你依赖的Guava包重命名,让它和Spark自带的Guava完全隔离。修改你的build.sbt,添加Shade规则:

name := "bigquer-connector"
version := "0.1"
scalaVersion := "2.11.8"
test in assembly := {}
assemblyJarName in assembly := "BigQueryConnector.jar"

// 新增Shade规则,将Guava包重命名为shaded.com.google.common
assemblyShadeRules in assembly := Seq(
  ShadeRule.rename("com.google.common.**" -> "shaded.com.google.common.@1")
    .inLibrary("com.google.guava" % "guava" % "30.0-jre")
    .inLibrary("com.google.cloud.spark" %% "spark-bigquery" % "0.18.0")
    .inProject
)

assemblyMergeStrategy in assembly := {
 case x if x.startsWith("META-INF") => MergeStrategy.discard
 case x => val oldStrategy = (assemblyMergeStrategy in assembly).value
 oldStrategy(x)
}

libraryDependencies += ("com.google.cloud.spark" %% "spark-bigquery" % "0.18.0")
 .exclude("com.google.guava", "guava")
 .exclude("org.glassfish.jersey.bundles.repackaged", "jersey-guava")
libraryDependencies += "com.google.guava" % "guava" % "30.0-jre"
libraryDependencies += ("org.apache.spark" % "spark-core_2.11" % "2.3.1")
 .exclude("com.google.guava", "guava")
 .exclude("org.glassfish.jersey.bundles.repackaged", "jersey-guava")
libraryDependencies += ("org.apache.spark" % "spark-sql_2.11" % "2.3.1")
 .exclude("com.google.guava", "guava")
 .exclude("org.glassfish.jersey.bundles.repackaged", "jersey-guava")

修改后重新执行sbt assembly打包,这样你的fat jar里的Guava类都会被重命名为shaded.com.google.common开头,和Spark自带的com.google.common完全隔离开,从根源上解决版本冲突问题。

验证打包结果

打包完成后,你可以用下面的命令确认Guava包已经被成功重命名:

jar tf BigQueryConnector.jar | grep shaded.com.google.common

如果输出一堆以shaded.com.google.common开头的类,就说明打包成功了。

内容的提问来源于stack exchange,提问作者Anoop Deshpande

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:05:16