测试提交Spark作业时遭遇java.lang.NoSuchMethodException报错求助
先看看你提交作业的命令和报错信息:
jianrui@spark:~$ sudo $SPARK_HOME/bin/spark-submit --class com.test.spark.FirstScalaExample --master spark://spark.sparkstreaming.i10.internal.cloudapp.net:7077 /opt/spark/FirstScalaExample-0.0.1.jar
报错内容:
Exception in thread "main" java.lang.NoSuchMethodException: com.test.spark.FirstScalaExample.main([Ljava.lang.String;)
at java.lang.Class.getMethod(Class.java:1786)
at org.apache.spark.deploy.JavaMainApplicati...
这个错误我之前踩过好几次,本质就是Spark找不到你指定主类里的标准main方法,或者主类本身有问题。给你梳理几个最可能的原因和对应的解决办法:
1. 主类的main方法签名不对
Scala里的main方法有严格的格式要求,差一点都不行:
- 方法名必须是小写的main,不能写成Main或者其他变体
- 参数必须是
Array[String]类型,不能是List或者其他集合 - 最好把main方法放在Scala的
object里(因为object里的方法默认是静态的,Spark能直接找到),如果非要放在class里,得加@scala.annotation.static注解标记成静态方法
给你个正确的示例:
package com.test.spark object FirstScalaExample { def main(args: Array[String]): Unit = { // 这里写你的Spark业务逻辑 println("Spark作业启动成功~") } }
2. 打包后jar包里找不到主类
你可以先检查一下jar包的内容,确认主类是否在正确的路径下:
jar tf /opt/spark/FirstScalaExample-0.0.1.jar
执行后看看输出里有没有com/test/spark/FirstScalaExample.class(如果是object的话,还会有FirstScalaExample$.class这个文件),要是找不到,说明打包的时候没把主类包含进去,得重新调整打包配置。
3. --class参数的全类名写错了
Scala对大小写非常敏感,仔细核对--class后面的内容:
- 包名、类名的大小写必须和代码里完全一致,比如
com.test.spark.firstscalaexample和com.test.spark.FirstScalaExample是两个完全不同的路径 - 主类是object的话,直接写它的全类名就行,不需要加末尾的$符号
4. 打包工具(sbt/maven)没配置主类
如果用sbt打包,记得在build.sbt里指定mainClass:
mainClass := Some("com.test.spark.FirstScalaExample")
如果用maven,要在shade或者assembly插件里配置主类,这样打包出来的jar包才会把主类信息写到Manifest里,Spark也能更准确地找到它。
5. 试试去掉sudo执行
你用sudo运行spark-submit可能会碰到权限或者环境变量的问题,比如sudo下的$SPARK_HOME和你普通用户的不一样,或者jar包对root用户没有可读权限。可以先尝试去掉sudo执行,或者先给jar包加可读权限:
chmod +r /opt/spark/FirstScalaExample-0.0.1.jar
按照上面的步骤排查一遍,应该就能解决这个问题了。
内容的提问来源于stack exchange,提问作者jianrui

