Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enum value serialization not stable #9642

Open
scabug opened this issue Feb 3, 2016 · 1 comment
Open

Enum value serialization not stable #9642

scabug opened this issue Feb 3, 2016 · 1 comment
Labels
Milestone

Comments

@scabug
Copy link

scabug commented Feb 3, 2016

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).

@scabug
Copy link
Author

scabug commented Feb 3, 2016

Imported From: https://issues.scala-lang.org/browse/SI-9642?orig=1
Reporter: @lrytz

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant