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

Fix #4440: Do not serialize the content of static objects #5775

Merged
merged 7 commits into from
Feb 2, 2019

Conversation

smarter
Copy link
Member

@smarter smarter commented Jan 22, 2019

In #4450 and Scala 2.12, readResolve is used to make sure deserializing
an object returns the singleton instance of the object, but this doesn't
prevent the fields of the objects from being serialized in the first
place even though they're not used. Scala 2.13 switched to using
writeReplace to completely bypass serialization of the object in
scala/scala#7297. This commit adapts this to
Dotty.

Co-Authored-By: Ingar Abrahamsen ingar@abrahams1.com
Co-Authored-By: Jason Zaugg jzaugg@gmail.com

Copy link
Member

@dottybot dottybot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello, and thank you for opening this PR! 🎉

All contributors have signed the CLA, thank you! ❤️

Have an awesome day! ☀️

@smarter
Copy link
Member Author

smarter commented Jan 25, 2019

@retronym feel free to review and let us know if there are relevant test cases from scalac we should add.

smarter added a commit to smarter/dotty that referenced this pull request Jan 25, 2019
To avoid deadlocks when combining objects, lambdas and multi-threading,
lambdas in objects are compiled to instance methods of the module class
instead of static methods (see tests/run/deadlock.scala and
scala/scala-dev#195 for details).

This has worked well for us so far but this is problematic for
serialization: serializing a lambda requires serializing all the values
it captures, if this lambda is in an object, this means serializing the
enclosing object, which fails if the object does not extend
Serializable.

Because serializing objects is basically free since scala#5775, it seems like
the simplest solution is to simply make all objects Serializable, this
certainly seems preferable to deadlocks.
smarter added a commit to smarter/dotty that referenced this pull request Jan 25, 2019
To avoid deadlocks when combining objects, lambdas and multi-threading,
lambdas in objects are compiled to instance methods of the module class
instead of static methods (see tests/run/deadlock.scala and
scala/scala-dev#195 for details).

This has worked well for us so far but this is problematic for
serialization: serializing a lambda requires serializing all the values
it captures, if this lambda is in an object, this means serializing the
enclosing object, which fails if the object does not extend
Serializable.

Because serializing objects is basically free since scala#5775, it seems like
the simplest solution is to simply make all objects Serializable, this
certainly seems preferable to deadlocks.
smarter added a commit to smarter/dotty that referenced this pull request Jan 25, 2019
To avoid deadlocks when combining objects, lambdas and multi-threading,
lambdas in objects are compiled to instance methods of the module class
instead of static methods (see tests/run/deadlock.scala and
scala/scala-dev#195 for details).

This has worked well for us so far but this is problematic for
serialization: serializing a lambda requires serializing all the values
it captures, if this lambda is in an object, this means serializing the
enclosing object, which fails if the object does not extend
Serializable.

Because serializing objects is basically free since scala#5775, it seems like
the simplest solution is to simply make all objects Serializable, this
certainly seems preferable to deadlocks.
@smarter smarter force-pushed the write-replace branch 2 times, most recently from 5db7456 to 3b9ed7f Compare January 25, 2019 22:55
smarter added a commit to smarter/dotty that referenced this pull request Jan 25, 2019
To avoid deadlocks when combining objects, lambdas and multi-threading,
lambdas in objects are compiled to instance methods of the module class
instead of static methods (see tests/run/deadlock.scala and
scala/scala-dev#195 for details).

This has worked well for us so far but this is problematic for
serialization: serializing a lambda requires serializing all the values
it captures, if this lambda is in an object, this means serializing the
enclosing object, which fails if the object does not extend
Serializable.

Because serializing objects is basically free since scala#5775, it seems like
the simplest solution is to simply make all objects Serializable, this
certainly seems preferable to deadlocks.
smarter added a commit to smarter/dotty that referenced this pull request Jan 26, 2019
To avoid deadlocks when combining objects, lambdas and multi-threading,
lambdas in objects are compiled to instance methods of the module class
instead of static methods (see tests/run/deadlock.scala and
scala/scala-dev#195 for details).

This has worked well for us so far but this is problematic for
serialization: serializing a lambda requires serializing all the values
it captures, if this lambda is in an object, this means serializing the
enclosing object, which fails if the object does not extend
Serializable.

Because serializing objects is basically free since scala#5775, it seems like
the simplest solution is to simply make all objects Serializable, this
certainly seems preferable to deadlocks.
smarter added a commit to smarter/dotty that referenced this pull request Jan 26, 2019
To avoid deadlocks when combining objects, lambdas and multi-threading,
lambdas in objects are compiled to instance methods of the module class
instead of static methods (see tests/run/deadlock.scala and
scala/scala-dev#195 for details).

This has worked well for us so far but this is problematic for
serialization: serializing a lambda requires serializing all the values
it captures, if this lambda is in an object, this means serializing the
enclosing object, which fails if the object does not extend
Serializable.

Because serializing objects is basically free since scala#5775, it seems like
the simplest solution is to simply make all objects Serializable, this
certainly seems preferable to deadlocks.
@smarter
Copy link
Member Author

smarter commented Jan 26, 2019

@nicolasstucki I just added support for classOf[X.type] where X is an object but this breaks the decompilation tests because it gets printed as classOf[X] and I can't figure out how to fix that, can you have a look ?

@nicolasstucki
Copy link
Contributor

I will have a look

@nicolasstucki nicolasstucki removed their assignment Jan 28, 2019
@nicolasstucki
Copy link
Contributor

Now the tests pass

smarter and others added 2 commits February 2, 2019 01:33
In scala#4450 and Scala 2.12, readResolve is used to make sure deserializing
an object returns the singleton instance of the object, but this doesn't
prevent the fields of the objects from being serialized in the first
place even though they're not used. Scala 2.13 switched to using
writeReplace to completely bypass serialization of the object in
scala/scala#7297. This commit adapts this to
Dotty.

Co-Authored-By: Ingar Abrahamsen <ingar@abrahams1.com>
Co-Authored-By: Jason Zaugg <jzaugg@gmail.com>
And use this in SyntheticMethods instead of the
impossible-to-write-in-user-code `classOf[Foo$]`. This is necessary if
we want decompilation to produce valid source code for objects.

Note that the decompilation printer is currently wrong here and will
print `classOf[Foo]` instead of `classOf[Foo.type]`.
@smarter smarter merged commit 03887b7 into scala:master Feb 2, 2019
smarter added a commit to smarter/dotty that referenced this pull request Feb 2, 2019
To avoid deadlocks when combining objects, lambdas and multi-threading,
lambdas in objects are compiled to instance methods of the module class
instead of static methods (see tests/run/deadlock.scala and
scala/scala-dev#195 for details).

This has worked well for us so far but this is problematic for
serialization: serializing a lambda requires serializing all the values
it captures, if this lambda is in an object, this means serializing the
enclosing object, which fails if the object does not extend
Serializable.

Because serializing objects is basically free since scala#5775, it seems like
the simplest solution is to simply make all objects Serializable, this
certainly seems preferable to deadlocks.
@allanrenucci allanrenucci deleted the write-replace branch February 2, 2019 21:56
smarter added a commit to dotty-staging/dotty that referenced this pull request Feb 3, 2019
To avoid deadlocks when combining objects, lambdas and multi-threading,
lambdas in objects are compiled to instance methods of the module class
instead of static methods (see tests/run/deadlock.scala and
scala/scala-dev#195 for details).

This has worked well for us so far but this is problematic for
serialization: serializing a lambda requires serializing all the values
it captures, if this lambda is in an object, this means serializing the
enclosing object, which fails if the object does not extend
Serializable.

Because serializing objects is basically free since scala#5775, it seems like
the simplest solution is to simply make all objects Serializable, this
certainly seems preferable to deadlocks.

For some reason, this commit causes the issue described in scala#3383 to
reappear, we add a workaround for that in Trees.scala.
smarter added a commit to dotty-staging/dotty that referenced this pull request Feb 3, 2019
To avoid deadlocks when combining objects, lambdas and multi-threading,
lambdas in objects are compiled to instance methods of the module class
instead of static methods (see tests/run/deadlock.scala and
scala/scala-dev#195 for details).

This has worked well for us so far but this is problematic for
serialization: serializing a lambda requires serializing all the values
it captures, if this lambda is in an object, this means serializing the
enclosing object, which fails if the object does not extend
Serializable.

Because serializing objects is basically free since scala#5775, it seems like
the simplest solution is to simply make all objects Serializable, this
certainly seems preferable to deadlocks.

For some reason, this commit causes the issue described in scala#3383 to
reappear, we add a workaround for that in Trees.scala.
smarter added a commit to dotty-staging/dotty that referenced this pull request Feb 3, 2019
To avoid deadlocks when combining objects, lambdas and multi-threading,
lambdas in objects are compiled to instance methods of the module class
instead of static methods (see tests/run/deadlock.scala and
scala/scala-dev#195 for details).

This has worked well for us so far but this is problematic for
serialization: serializing a lambda requires serializing all the values
it captures, if this lambda is in an object, this means serializing the
enclosing object, which fails if the object does not extend
Serializable.

Because serializing objects is basically free since scala#5775, it seems like
the simplest solution is to simply make all objects Serializable, this
certainly seems preferable to deadlocks.

This commit causes a cyclic reference to happen in some cases, we add a
workaround to avoid this in Trees.scala and fix it properly in the
commit.
smarter added a commit to dotty-staging/dotty that referenced this pull request Feb 6, 2019
To avoid deadlocks when combining objects, lambdas and multi-threading,
lambdas in objects are compiled to instance methods of the module class
instead of static methods (see tests/run/deadlock.scala and
scala/scala-dev#195 for details).

This has worked well for us so far but this is problematic for
serialization: serializing a lambda requires serializing all the values
it captures, if this lambda is in an object, this means serializing the
enclosing object, which fails if the object does not extend
Serializable.

Because serializing objects is basically free since scala#5775, it seems like
the simplest solution is to simply make all objects Serializable, this
certainly seems preferable to deadlocks.

This commit causes a cyclic reference to happen in some cases, we add a
workaround to avoid this in Trees.scala and fix it properly in the
commit.
smarter added a commit to dotty-staging/dotty that referenced this pull request Feb 6, 2019
To avoid deadlocks when combining objects, lambdas and multi-threading,
lambdas in objects are compiled to instance methods of the module class
instead of static methods (see tests/run/deadlock.scala and
scala/scala-dev#195 for details).

This has worked well for us so far but this is problematic for
serialization: serializing a lambda requires serializing all the values
it captures, if this lambda is in an object, this means serializing the
enclosing object, which fails if the object does not extend
Serializable.

Because serializing objects is basically free since scala#5775, it seems like
the simplest solution is to simply make all objects Serializable, this
certainly seems preferable to deadlocks.

This commit causes a cyclic reference to happen in some cases, we add a
workaround to avoid this in Trees.scala and fix it properly in the
commit.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants