这不是关于Spark的问题,而是关于Scala如何生成代码的问题。请记住,Scalaobject几乎是一个充满静态方法的Java类。考虑一个像这样的简单示例:
object foo { val value = 42 def func(i: Int): Int = i + value def main(args: Array[String]): Unit = { println(Seq(1, 2, 3).map(func).sum) }}那将被翻译成3个Java类。其中之一将是闭包,该闭包是map方法的参数。javap在该类上使用将产生以下内容:
public final class foo$$anonfun$main$1 extends scala.runtime.AbstractFunction1$mcII$sp implements scala.Serializable { public static final long serialVersionUID; public final int apply(int); public int apply$mcII$sp(int); public final java.lang.Object apply(java.lang.Object); public foo$$anonfun$main$1();}请注意,没有任何字段。如果您查看反汇编的字节码,它所做的就是调用func()方法。在Spark中运行时,这是将被序列化的实例;由于它没有字段,因此不需要序列化。
至于您的问题,即如何初始化静态对象,您可以在关闭开始时调用一个幂等的初始化函数。第一个将触发初始化,随后的调用将成为无操作。不过,清理工作要复杂得多,因为我不熟悉执行“在所有执行程序上运行此代码”之类的API。
如果需要清理,一种有用的方法在此博客的“ setup()和cleanup()”部分中进行了说明。
编辑:只是为了澄清,这是实际进行调用的方法的反汇编。
public int apply$mcII$sp(int); Code: 0: getstatic #29; //Field foo$.MODULE$:Lfoo$; 3: iload_1 4: invokevirtual #32; //Method foo$.func:(I)I 7: ireturn
了解它如何仅引用保存单例的静态字段并调用该func()方法。



