1

したがって、次のユースケースがあります。

DSL のようなインターフェイスを提供することで、特定のドメインでの Spark データフレームの使用を簡素化しています。このコードはすべて、Maven シェード プラグインによって作成されたファット jar に入れられます。(fat jar = spark と hadoop の依存関係なし)

このファット jar にはメイン クラスがあり、それを JavaMain と呼びましょう。

JavaMain 内で、残りの呼び出しを行って、内容が有効な DSL である文字列を取得します。

初期設定オブジェクトを使用して 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

詳細なコンテキスト:

これを試してみると、クラスパスに問題がありました。私はそれらすべてを解決できていないようですが。

以前に設定オブジェクトを作成したとき、私は次のようなことをしていました:

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
}

ただし、spark サブミットを実行すると、クラスパスに spark および hadoop 関連の jar しかないため、これは機能していないように見えました。

次に、クラスパスに次を追加しました。

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 内の同じオブジェクトの import と new は問題を引き起こしません)。

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)
   """
)

私が知っていて気になっているもう 1 つの詳細は、IMain がクラスローダーを内部的に変更することです。それが問題の原因であるかどうかはわかりません。

どんな助けでも大歓迎です。

4

1 に答える 1

0

わかった。そこで、私たちは問題を解決する方法を考え出しました。

IMain は、別のクラスローダーを使用してクラスをロードし、次にそれらがロードされるはずのクラスをロードすると思います。とにかく、以下は問題を解決し、他の人に見てもらいます。

val interpreter = new IMain(settings){
  override protected def parentClassLoader: ClassLoader = this.getClass.getClassLoader
}
于 2015-11-25T15:19:23.300 に答える