记录一个比较典型的问题,先讲一下背景,有这么一个用java写的类
java
public class JavaClass0 implements Serializable {
private static String name;
public static JavaClass0 getName(String str) {
if (name == null) {
name=str;
}
return name;
}
...
}
然后在spark中使用的时候:
scala
//driver端
JavaClass0.getName("张三")//得到张三
JavaClass0.getName("李四")//得到张三
df.foreachPartition{//executor端
m=>
JavaClass0.getName("王五")//得到王五
JavaClass0.getName("钱六")//得到王五
}
原因:
scala的object对应的就是java的静态成员,可以反过来理解java的所有静态成员可被抽取成伴生对象(虽然现实中是scala最终编译成java)。以上面的JavaClass0 例子可理解为等价的scala代码为:
scala
class JavaClass0 {
...
}
//伴生对象
object JavaClass0 {
private var name:String = null
getName(str:String) {
if (name == null) {
name=str
}
return name;
}
}
可以看到,JavaClass0并没有被传到executor中,而是重新初始化了一遍。事实也是如此。
Objects, as singletons, are never shipped to executors. There initialized locally, whenever objects is accessed for the first time.
object是不会被传递到executor的,他们在首次被访问的时候,在executor本地做初始化。只要executor的jvm不消亡,就不会再次初始化。
参考
Sharing objects in Spark
Spark Object (singleton) serialization on executors
Java中static作用及用法详解