Reputation: 8057
I've this small scala code snipet:
@SerialVersionUID(43L) class p(val a:Int=14,val b:Double=3.0) extends Serializable{
}
import java.io._
val out = new ObjectOutputStream(new FileOutputStream("my.obj"))
out.writeObject(new p(5,7))
out.close()
val in = new ObjectInputStream(new FileInputStream("my.obj"))
val savedPerson=in.readObject.asInstanceOf[p]
println(savedPerson.a)
When I run it on windows or mac, it prints out a huge exception information:
java.io.NotSerializableException: Main$$anon$1
at java.base/java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.base/java.io.ObjectOutputStream.defaultWriteFields(Unknown Source)
at java.base/java.io.ObjectOutputStream.writeSerialData(Unknown Source)
at java.base/java.io.ObjectOutputStream.writeOrdinaryObject(Unknown Source)
at java.base/java.io.ObjectOutputStream.writeObject0(Unknown Source)
at java.base/java.io.ObjectOutputStream.writeObject(Unknown Source)
at Main$$anon$1.errorFunction(ch09.scala:52)
at Main$$anon$1.<init>(ch09.scala:110)
at Main$.main(ch09.scala:1)
at Main.main(ch09.scala)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at scala.reflect.internal.util.ScalaClassLoader.$anonfun$run$2(ScalaClassLoader.scala:98)
at scala.reflect.internal.util.ScalaClassLoader.asContext(ScalaClassLoader.scala:32)
at scala.reflect.internal.util.ScalaClassLoader.asContext$(ScalaClassLoader.scala:30)
at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.asContext(ScalaClassLoader.scala:129)
at scala.reflect.internal.util.ScalaClassLoader.run(ScalaClassLoader.scala:98)
at scala.reflect.internal.util.ScalaClassLoader.run$(ScalaClassLoader.scala:90)
at scala.reflect.internal.util.ScalaClassLoader$URLClassLoader.run(ScalaClassLoader.scala:129)
at scala.tools.nsc.CommonRunner.run(ObjectRunner.scala:22)
at scala.tools.nsc.CommonRunner.run$(ObjectRunner.scala:21)
at scala.tools.nsc.ObjectRunner$.run(ObjectRunner.scala:39)
at scala.tools.nsc.CommonRunner.runAndCatch(ObjectRunner.scala:29)
at scala.tools.nsc.CommonRunner.runAndCatch$(ObjectRunner.scala:28)
at scala.tools.nsc.ObjectRunner$.runAndCatch(ObjectRunner.scala:39)
at scala.tools.nsc.ScriptRunner.runCompiled(ScriptRunner.scala:170)
at scala.tools.nsc.ScriptRunner.$anonfun$runScript$1(ScriptRunner.scala:187)
at scala.tools.nsc.ScriptRunner.$anonfun$runScript$1$adapted(ScriptRunner.scala:187)
at scala.tools.nsc.ScriptRunner.$anonfun$withCompiledScript$2(ScriptRunner.scala:156)
at scala.tools.nsc.ScriptRunner.runScript(ScriptRunner.scala:124)
at scala.tools.nsc.ScriptRunner.runScriptAndCatch(ScriptRunner.scala:200)
at scala.tools.nsc.MainGenericRunner.runTarget$1(MainGenericRunner.scala:70)
at scala.tools.nsc.MainGenericRunner.run$1(MainGenericRunner.scala:85)
at scala.tools.nsc.MainGenericRunner.process(MainGenericRunner.scala:96)
at scala.tools.nsc.MainGenericRunner$.main(MainGenericRunner.scala:101)
at scala.tools.nsc.MainGenericRunner.main(MainGenericRunner.scala)
What error is this? How can I fix it? I don't quite get this. Thanks!
Upvotes: 2
Views: 316
Reputation: 39577
I see from your stack trace that you're using the script runner:
scala -nc noser.scala
where I've named the script as in Yessir, no sir, because there is no serialization happening.
-nc
avoids starting the compile server daemon.
If the script runner doesn't see an object with a main method, it packages your script code in a class that is local to a main method it constructs for you.
def main(args: Array[String]) = { class anon_class { code } ; new anon_class() }
Your code is run in the constructor, which isn't a good idea either.
You can see this with -Xprint:typer,flatten
. Or experiment with -Xprint:all
.
Your serializable class has an outer pointer to the anonymous local class, and the anonymous class is not serializable.
Maybe the outer pointer is just a bug. Or not, see the reference below. It needs a hint to eliminate the outer pointer, such as making the class final
.
I see there have been similar bugs such as this one where the enclosing module is captured by a lambda.
Your workaround is to put your code in the main method of an object, or wrap everything in App
.
object Main extends App {
// code
}
Another workaround is to make your serializable class final
. There is discussion on this ticket and the related ticket and fix.
Upvotes: 3