我正在一个系统上工作,我可以让用户编写DSLS,并在运行时将其作为Type的实例加载,并且可以将它们应用于RDD。整个应用程序都作为提交火花的应用程序运行,我使用ScriptEngine引擎来编译用Scala本身编写的DSL。每个测试在SBT和IntelliJ中都可以正常工作。但是在执行spark-submit时,我的胖罐中可用的我自己的类型无法在Script中导入。我按如下所示初始化脚本引擎。
val engine: ScriptEngine = new ScriptEngineManager().getEngineByName("scala")
private val settings: Settings = engine.asInstanceOf[scala.tools.nsc.interpreter.IMain].settings
settings.usejavacp.value = true
settings.embeddedDefaults[DummyClass]
private val loader: ClassLoader = Thread.currentThread().getContextClassLoader
settings.embeddedDefaults(loader)
在提交火花期间,这似乎是类加载器的问题。但是我无法弄清为什么我的jar中也有我的类型,而我的脚本中也有spark-submit的主程序,该类型在同一JVM中创建的脚本中不可用。 scala scala编译器,scala-reflect和scala库版本为2.11.8。一些帮助将不胜感激。
答案 0 :(得分:0)
我找到了可行的解决方案。通过遍历代码和大量调试,我最终发现ScriptEngine通过使用用于创建它的Classloader的Classpath字符串为其自身创建了Classloader。在提交spark的情况下,spark创建了一个特殊的类加载器,它可以从本地文件和hdfs文件中读取。但是从该类加载器获得的类路径字符串将不会包含HDFS中存在的应用程序jar。
通过在初始化之前将应用程序jar手动附加到ScriptEngine类路径,可以解决我的问题。为此,我必须先将HDFS中的应用程序jar本地下载到本地,然后再附加它。