我遇到了一个反序列化问题,只有在我通过测试运行程序运行我的代码时才会显示该问题。运行组装的 uberjar(使用 AOT 编译)不会显示此行为,也不会从 REPL 运行相同的代码。尝试过的测试运行程序是:cognitect/test-runner 和 lambdaisland/kaocha。
我的一般问题是:为什么在测试运行器中与 REPL 或 uberjar 中序列化的行为不同?
我最初怀疑 AOT 编译导致了差异,但我希望在 REPL 中也能看到异常。
以下是堆栈异常堆栈跟踪的相关部分:
java.lang.ClassCastException: cannot assign instance of java.lang.invoke.SerializedLambda to field org.apache.spark.rdd.MapPartitionsRDD.f of type scala.Function3 in instance of org.apache.spark.rdd.MapPartitionsRDD
at java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2233)
at java.io.ObjectStreamClass.setObjFieldValues(ObjectStreamClass.java:1405)
... trimmed for easier reading ...
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431)
at org.apache.spark.serializer.JavaDeserializationStream.readObject(JavaSerializer.scala:76)
at org.apache.spark.serializer.JavaSerializerInstance.deserialize(JavaSerializer.scala:115)
at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:83)
at org.apache.spark.scheduler.Task.run(Task.scala:131)
at org.apache.spark.executor.Executor$TaskRunner.$anonfun$run$3(Executor.scala:497)
at org.apache.spark.util.Utils$.tryWithSafeFinally(Utils.scala:1439)
at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:500)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
更多详细信息,以防万一:我的 Clojure 应用程序通过 Scala/Java 互操作使用 Spark。当执行程序/工作进程收到 MapPartitionsRDD
对象形式的新任务时,会发生反序列化异常。
下面是我创建的一个简单的 deftype
,它扩展了 Spark 提供的 MapFunction
接口。此接口允许将函数序列化和广播到工作进程,并由 MapPartitionsRDD
使用,尽管我不确定如何使用。
(deftype CljMapFunction [func]
org.apache.spark.api.java.function.MapFunction
(call [_ var1]
(-> var1 row/row->map func row/to-row))) ; The row/* functions are my own.
当我将 CljMapFunction
的实例传递给 the java-specific map
method of a spark Dataset 方法时,如果代码由测试运行程序执行,我会看到上述异常。同样,组装的 uberjars 和从 REPL 运行的行为都符合预期。