Open
Description
Serializing an enum value depends on members of the the enum object being initialized or not. Note that for most users the serialized bytes don't matter, because Enumeration class has a readResolve
method that returns the correct value instance.
object TestEnum extends Enumeration {
val Left, Centre, Right = Value
}
def serialize(x: Any) = {
import java.io._
val baos = new ByteArrayOutputStream(1024);
val oos = new ObjectOutputStream(baos);
oos.writeObject(x);
oos.flush();
baos.toByteArray
}
import java.util.Arrays
val t = TestEnum.Right
val ser1 = serialize(t) // serialize t
val values = TestEnum.values // get the list of possible values
val ser2 = serialize(t) // serialize the same t again
println(Arrays.equals(ser1, ser2)) // outputs false
The abstract class Enumeration has member objects ValueOrdering and ValueSet, which may or may not be initialized when serializing. They should be marked @transient
, but that doesn't work for member objects. Test for that:
class C extends Serializable {
@transient // not respected
object O extends Serializable { val x = 0 } // needs to be serializable
// replace the object definition by the following, then serialization is stable
// class O { val x = 0 }
// @transient
// lazy val O = new O
}
object SD {
import java.io._
def serialize(obj: AnyRef): Array[Byte] = {
val buffer = new ByteArrayOutputStream
val out = new ObjectOutputStream(buffer)
out.writeObject(obj)
buffer.toByteArray
}
def deserialize(a: Array[Byte]): AnyRef = {
val in = new ObjectInputStream(new ByteArrayInputStream(a))
in.readObject
}
def serializeDeserialize[T <: AnyRef](obj: T) = deserialize(serialize(obj)).asInstanceOf[T]
}
import SD._
import java.util.Arrays.{equals => arrComp}
object Test extends App {
val c = new C
val a = serialize(c)
c.O
val b = serialize(c)
println(arrComp(a, b))
}
An easy fix may be to add empty readObject/writeObject methods to Enumeration (to investigate the consequences).