-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix #4440: Do not serialize the content of static objects
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 <[email protected]> Co-Authored-By: Jason Zaugg <[email protected]>
- Loading branch information
1 parent
af9264d
commit 3b9ed7f
Showing
11 changed files
with
159 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Copied from https://github.com/scala/scala/blob/2.13.x/src/library/scala/runtime/ModuleSerializationProxy.java | ||
// TODO: Remove this file once we switch to the Scala 2.13 stdlib since it already contains it. | ||
|
||
/* | ||
* Scala (https://www.scala-lang.org) | ||
* | ||
* Copyright EPFL and Lightbend, Inc. | ||
* | ||
* Licensed under Apache License 2.0 | ||
* (http://www.apache.org/licenses/LICENSE-2.0). | ||
* | ||
* See the NOTICE file distributed with this work for | ||
* additional information regarding copyright ownership. | ||
*/ | ||
|
||
package scala.runtime; | ||
|
||
import java.io.Serializable; | ||
import java.security.AccessController; | ||
import java.security.PrivilegedActionException; | ||
import java.security.PrivilegedExceptionAction; | ||
import java.util.HashSet; | ||
import java.util.Set; | ||
|
||
/** A serialization proxy for singleton objects */ | ||
public final class ModuleSerializationProxy implements Serializable { | ||
private static final long serialVersionUID = 1L; | ||
private final Class<?> moduleClass; | ||
private static final ClassValue<Object> instances = new ClassValue<Object>() { | ||
@Override | ||
protected Object computeValue(Class<?> type) { | ||
try { | ||
return AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> type.getField("MODULE$").get(null)); | ||
} catch (PrivilegedActionException e) { | ||
return rethrowRuntime(e.getCause()); | ||
} | ||
} | ||
}; | ||
|
||
private static Object rethrowRuntime(Throwable e) { | ||
Throwable cause = e.getCause(); | ||
if (cause instanceof RuntimeException) throw (RuntimeException) cause; | ||
else throw new RuntimeException(cause); | ||
} | ||
|
||
public ModuleSerializationProxy(Class<?> moduleClass) { | ||
this.moduleClass = moduleClass; | ||
} | ||
|
||
@SuppressWarnings("unused") | ||
private Object readResolve() { | ||
return instances.get(moduleClass); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import java.io.File | ||
|
||
object Module { | ||
val data = new Array[Byte](32 * 1024 * 1024) | ||
} | ||
|
||
object Test { | ||
private val readResolve = classOf[scala.runtime.ModuleSerializationProxy].getDeclaredMethod("readResolve") | ||
readResolve.setAccessible(true) | ||
|
||
val testClassesDir = new File(Module.getClass.getClassLoader.getResource("Module.class").toURI).getParentFile | ||
def main(args: Array[String]): Unit = { | ||
for (i <- 1 to 256) { | ||
// This would "java.lang.OutOfMemoryError: Java heap space" if ModuleSerializationProxy | ||
// prevented class unloading. | ||
deserializeDynamicLoadedClass() | ||
} | ||
} | ||
|
||
def deserializeDynamicLoadedClass(): Unit = { | ||
val loader = new java.net.URLClassLoader(Array(testClassesDir.toURI.toURL), ClassLoader.getSystemClassLoader) | ||
val moduleClass = loader.loadClass("Module$") | ||
assert(moduleClass ne Module.getClass) | ||
val result = readResolve.invoke(new scala.runtime.ModuleSerializationProxy(moduleClass)) | ||
assert(result.getClass == moduleClass) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters