I meet a very strange problem on Spark about serialization. The code is as below:
class PLSA(val sc : SparkContext, val numOfTopics : Int) extends Serializable
{
Anonymous functions serialize their containing class. When you map {doc => DocumentParameter(doc, numOfTopics)}
, the only way it can give that function access to numOfTopics
is to serialize the PLSA
class. And that class can't actually be serialized, because (as you can see from the stacktrace) it contains the SparkContext
which isn't serializable (Bad Things would happen if individual cluster nodes had access to the context and could e.g. create new jobs from within a mapper).
In general, try to avoid storing the SparkContext
in your classes (edit: or at least, make sure it's very clear what kind of classes contain the SparkContext
and what kind don't); it's better to pass it as a (possibly implicit
) parameter to individual methods that need it. Alternatively, move the function {doc => DocumentParameter(doc, numOfTopics)}
into a different class from PLSA
, one that really can be serialized.
(As multiple people have suggested, it's possible to keep the SparkContext
in the class but marked as @transient
so that it won't be serialized. I don't recommend this approach; it means the class will "magically" change state when serialized (losing the SparkContext
), and so you might end up with NPEs when you try to access the SparkContext
from inside a serialized job. It's better to maintain a clear distinction between classes that are only used in the "control" code (and might use the SparkContext
) and classes that are serialized to run on the cluster (which must not have the SparkContext
)).