主文件首行添加package时触发ClassNotFoundException的原因排查
Spark提交时
ClassNotFoundException: GApp的原因解析 问题场景还原
你遇到的情况是这样的:
- 用
sbt package打包Spark应用时,代码带package mygraph声明的话,提交spark-submit会抛出ClassNotFoundException: GApp - 删掉首行的
package mygraph后,应用就能正常运行 - 你的
build.sbt配置如下:
name := "ag" version := "1.0" artifactName := { (sv, md, art) => "g.jar" } scalaVersion := "2.11.8" assemblyJarName in assembly := "G.jar" resolvers += "Spark Packages Repo" at "http://dl.bintray.com/spark-packages/maven" libraryDependencies ++= Seq( "org.apache.spark" %% "spark-sql" % "2.0.1" % "provided", "org.apache.spark" %% "spark-graphx" % "2.0.1" % "provided", "neo4j-contrib" % "neo4j-spark-connector" % "2.0.0-M2" % "provided" )
核心原因:全限定类名不匹配
这其实是个很常见的类路径问题,本质是你提交时指定的类名和实际类的全限定名不一致:
- 当代码加上
package mygraph时,GApp的完整类名是mygraph.GApp(包名+类名),而不是单纯的GApp - Spark在加载主类时,会根据你指定的类名去jar包对应的路径找class文件:
- 带包声明的
GApp会被放在jar里的mygraph/GApp.class路径下 - 如果你提交时只写
--class GApp,Spark会去根目录找GApp.class,自然找不到
- 带包声明的
- 删掉
package声明后,GApp属于默认的根包,对应的class文件在jar根目录,所以指定GApp就能正常找到
两种解决办法
办法一:提交时使用全限定类名
在执行spark-submit命令时,把主类参数改成完整的包名+类名:
spark-submit --class mygraph.GApp --master [你的Spark Master地址] g.jar
办法二:在build.sbt中指定默认主类
如果你不想每次提交都写长类名,可以在build.sbt里添加主类配置,这样打包后的jar会默认使用这个主类:
// 新增这一行,指定全限定主类名 mainClass in Compile := Some("mygraph.GApp")
之后直接执行spark-submit g.jar就能正常运行了
内容的提问来源于stack exchange,提问作者Litchy
相关产品推荐
相关产品推荐

