的InvocationTargetException。无法将类X强制转换为类X.在Scala中调用时通过spark-submit调用

时间:2015-11-24 05:51:02

标签: java scala apache-spark scala-compiler

所以,我有以下用例。

我通过提供类似DSL的界面来简化特定域的Spark数据帧的使用。 所有这些代码都放在由maven shade插件创建的胖罐子里。 (胖罐=没有火花和hadoop依赖)

这个胖子有一个主类,我们称之为JavaMain。

在JavaMain中,我进行休息调用以获取其内容为有效DSL的字符串。

我使用初始Settings对象实例化一个IMain对象。 我绑定了一些变量。使用imain.bind方法。

但是此绑定失败并出现以下错误:

Set failed in bind(results, com.dhruv.dsl.DslDataFrame.DSLResults, com.dhruv.dsl.DslDataFrame$DSLResults@7650a5f3)
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:734)
    at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.callEither(IMain.scala:738)
    at scala.tools.nsc.interpreter.IMain.bind(IMain.scala:625)
    at scala.tools.nsc.interpreter.IMain.bind(IMain.scala:661)
    at scala.tools.nsc.interpreter.IMain.bind(IMain.scala:662)
    at com.thoughtworks.dsl.DSL.run(DSL.scala:44)
    at com.thoughtworks.dsl.JavaMain.run(JavaMain.java:30)
    at com.thoughtworks.dsl.JavaMain.main(JavaMain.java:43)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.apache.spark.deploy.SparkSubmit$.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:665)
    at org.apache.spark.deploy.SparkSubmit$.doRunMain$1(SparkSubmit.scala:170)
    at org.apache.spark.deploy.SparkSubmit$.submit(SparkSubmit.scala:193)
    at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:112)
    at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
Caused by: java.lang.ClassCastException: com.thoughtworks.dsl.DslDataFrame$DSLResults cannot be cast to com.thoughtworks.dsl.DslDataFrame$DSLResults
    at $line3.$eval$.set(<console>:6)
    at $line3.$eval.set(<console>)
    ... 21 more

更多背景信息:

尝试此操作时,我遇到了类路径问题。虽然看起来我无法解决所有问题。

在创建Setting对象之前,我正在做这样的事情:

val settings = {
  val x = new Settings()
  x.classpath.value += File.pathSeparator + System.getProperty("java.class.path")
  x.usejavacp.value = true
  x.verbose.value = true
  x
}

然而,这似乎不起作用,因为当做一个火花提交时,这只有类似路径上的火花和hadoop相关的罐子。

然后我将以下内容添加到类路径中:

val urLs: Array[URL] = Thread.currentThread.getContextClassLoader.asInstanceOf[URLClassLoader].getURLs

并做了以下事情:

val settings = {
  val x = new Settings()
  x.classpath.value += File.pathSeparator + urLs(0)
  x.usejavacp.value = true
  x.verbose.value = true
  x
}

这是我用来绑定对象的代码:

interpreter.bind("notagin", new SomeDummyObject)

这会引发我之前附加的异常。 有趣的是,以下代码有效:(即,在Interpreter中导入和使用相同的新对象不会导致问题)

interpreter.interpret(
  """
      import com.dhruv.dsl.operations._
      import com.dhruv.dsl.implicits._
      import com.dhruv.dsl.DslDataFrame._
      import org.apache.spark.sql.Column
      import com.dhruv.dsl._
      implicit def RichColumn(column: Column): RichColumn = new RichColumn(column)
      val justdont = new SomeDummyObject()
      justdont.justdontcallme(thatJson)
   """
)

我知道并且困扰我的另一个细节是,IMain内部确实更改了类加载器。不确定是否是导致问题的原因。

任何帮助都不仅仅是值得赞赏的。

1 个答案:

答案 0 :(得分:0)

好。所以我们想出了如何为我们解决问题。

我认为IMain使用不同的类加载器来加载类,然后加载它们应该加载的类。无论如何,以下解决了这个问题,让其他人看看。

val interpreter = new IMain(settings){
  override protected def parentClassLoader: ClassLoader = this.getClass.getClassLoader
}