我正在以我的超级JAR为主要类的EMR步骤中执行spark-submit脚本,例如
spark-submit \
....
--class ${MY_CLASS} "${SUPER_JAR_S3_PATH}"
...等等
但Spark默认情况下会加载jar文件:/usr/lib/spark/jars/guice-3.0.jar,其中包含com.google.inject.internal.InjectorImpl,该类也在Guice-4.x中我的超级JAR中的jar。我的服务正在启动时,这会导致java.lang.IllegalAccessError
。
我尝试在spark-submit
中设置一些Spark conf,以将我的超级jar放在类路径中,希望在Spark加载guice-3.0.jar之前先加载它。看起来像:
--jars "${ASSEMBLY_JAR_S3_PATH}" \
--driver-class-path "/etc/hadoop/conf:/etc/hive/conf:/usr/lib/hadoop-lzo/lib/*:/usr/share/aws/aws-java-sdk/*:/usr/share/aws/emr/emrfs/conf:/usr/share/aws/emr/emrfs/lib/*:/usr/share/aws/emr/emrfs/auxlib/*:${SUPER_JAR_S3_PATH}" \
--conf spark.executor.extraClassPath="/etc/hadoop/conf:/etc/hive/conf:/usr/lib/hadoop-lzo/lib/*:/usr/share/aws/aws-java-sdk/*:/usr/share/aws/emr/emrfs/conf:/usr/share/aws/emr/emrfs/lib/*:/usr/share/aws/emr/emrfs/auxlib/*:${SUPER_JAR_S3_PATH}" \
但这会导致相同的错误。
是否有一种方法可以从默认的Spark类路径中删除该guice-3.0.jar
,以便我的代码可以使用InjectorImpl
JAR中打包的Guice-4.x
?我也在客户端模式下运行Spark,因此无法使用spark.driver.userClassPathFirst
或spark.executor.userClassPathFirst
答案 0 :(得分:0)
一种方法是指向lib您的guice旧版jar所在的库,然后将其排除。
spark-submit
的示例shell脚本:
export latestguicejar='your path to latest guice jar'
#!/bin/sh
# build all other dependent jars in OTHER_JARS
JARS=`find /usr/lib/spark/jars/ -name '*.jar'`
OTHER_JARS=""
for eachjarinlib in $JARS ; do
if [ "$eachjarinlib" != "guice-3.0.jar" ]; then
OTHER_JARS=$eachjarinlib,$OTHER_JARS
fi
done
echo ---final list of jars are : $OTHER_JARS
echo $CLASSPATH
spark-submit --verbose --class <yourclass>
... OTHER OPTIONS
--jars $OTHER_JARS,$latestguicejar,APPLICATIONJARTOBEADDEDSEPERATELY.JAR
另请参阅holdens answer。检查您的Spark版本,可以使用什么。
根据文档runtime-environment userClassPathFirst
的最新版本提供了spark。
spark.executor.userClassPathFirst
spark.driver.userClassPathFirst
为此,您可以使uber jar具有所有应用程序级别的依赖关系。