2

I have Scala singleton objects Works and Broken that look very similar:

object Works {
  def i = ???
  val factory = new Serializable {
    def get = i
  }
}

object Broken extends A

trait A {
  def i = ???
  val factory = new Serializable {
    def get = i
  }
}

What I'd like to understand is why is Works.factory serializable but Broken.factory isn't?

1 Answer 1

3

To serialise a class all members must also be serialisable. However consider -Xprint:jvm output of the anonymous new Serializable in trait A

  final class anon$1 extends Object with java.io.Serializable {
    def get(): Nothing = anon$1.this.$outer.i();
    <synthetic> <paramaccessor> <artifact> private[this] val $outer: $line58.iw$A = _;
    def <init>($outer: $line58.iw$A): <$anon: Object> = {
      if ($outer.eq(null))
        throw null
      else
        anon$1.this.$outer = $outer;
      anon$1.super.<init>();
      ()
    }
  }

In particular note the member

<synthetic> <paramaccessor> <artifact> private[this] val $outer: $line58.iw$A = _;

The class of instance referenced by $outer is A, however trait A has not been declared as Serializable. Therefore serialisation of anonymous class referenced by Broken.factory fails.

On the other hand, consider -Xprint:jvm output of the anonymous new Serializable in object Works

  final class anon$1 extends Object with java.io.Serializable {
    def get(): Nothing = iw$Works.this.i();
    def <init>(): <$anon: Object> = {
      anon$1.super.<init>();
      ()
    }
  }

Notice there is no member (similar to $outer) that is not Serializable. Therefore serialisation of anonymous class referenced by Works.factory succeeds.

The fix is to make trait A serialisiable like so

trait A extends Serializable { ... }

however Java Object Serialization Specification warns

Serialization of inner classes (i.e., nested classes that are not static member classes), including local and anonymous classes, is strongly discouraged for several reasons. Because inner classes declared in non-static contexts contain implicit non-transient references to enclosing class instances, serializing such an inner class instance will result in serialization of its associated outer class instance as well.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.