Reputation: 49
I am trying to serialize a scala singleton object using the built in java object serialization library.
Here's an example of the serializer program:
object potato extends Serializable {
var dirt = 5
}
def main(args: Array[String]): Unit = {
val fileName = "potato.sav"
val potatoOutputStream = new ObjectOutputStream(new FileOutputStream(fileName))
potato.dirt = 12345
potatoOutputStream.writeObject(potato)
potatoOutputStream.close()
}
and here's an example of the deserializer program:
object potato extends Serializable {
var dirt = 5
}
def main(args: Array[String]): Unit = {
val fileName = "potato.sav"
val potatoInputStream = new ObjectInputStream(new FileInputStream(fileName))
val p = potatoInputStream.readObject.asInstanceOf[potato.type]
println("potato dirt quantity " + p.dirt)
}
this prints 5 instead of the expected 12345. I've looked at potato.sav in a hex editor and the number 12345 doesn't even show up, it appears to be a 'scala.runtime.ModuleSerializationProxy' and doesn't contain any field data. In fact, changing any of the numbers in the initializer or the main function results in a byte-for-byte identical serialized file :(
I kind of understand why this might be happening, and that deserializing a singleton object can't (or shouldn't) create another instance, but I would really like to find a way to make this, or something similar work. I don't need to use the built in serialization library, but I need a solution that doesn't require writing a custom serializer/deserializer for each individual singleton object.
Any help would be appreciated. Thanks!
edit: I am using objects here because I want many instances of anonymous subclasses of a certain type, each with custom logic for a DSL.
Unfortunately it seems like using object makes them not serializable because they are implemented as static classes, which java won't serialize. Structural types are out too because in scala 3 you can't access mutable state anymore as some kind of new and unexplained restriction, not to mention the performance problems with structural types.
Upvotes: 0
Views: 276
Reputation: 49
Ended up writing my own object serialization routine with some help from apache reflection utils. It's not pretty but it works.
def SerializeMembers(oos: ObjectOutputStream): Unit = {
val fields = FieldUtils.getAllFields(getClass)
for (f <- fields) {
val modifiers = f.getModifiers
val isNotFinal = (modifiers & Modifier.FINAL) == 0
if (isNotFinal) {
f.setAccessible(true)
oos.writeObject(f.get(this))
}
}
}
def DeserialzeMembers(ois: ObjectInputStream): Unit = {
val fields = FieldUtils.getAllFields(getClass)
for (f <- fields) {
val modifiers = f.getModifiers
val isNotFinal = (modifiers & Modifier.FINAL) == 0
if (isNotFinal) {
f.setAccessible(true)
val obj = ois.readObject()
f.set(this, obj)
}
}
}
Upvotes: 0
Reputation: 946
Members of a companion object are modeled as static
members in Java.
From the docs:
When using a companion object from Java code, the members will be defined
in a companion class with a static modifier.
This is called static forwarding.
It occurs even if you haven’t defined a companion class yourself.
So lookup how Java serialization works with static
fields.
If you have a mutable static field the changes made to that value will be lost.
Upvotes: 1