diff --git a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java index fca32fb4daf..6ae3a542c10 100644 --- a/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java +++ b/jdk/src/java.base/share/classes/java/io/ObjectInputStream.java @@ -40,6 +40,7 @@ import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import static java.io.ObjectStreamClass.processQueue; +import sun.misc.Unsafe; import sun.reflect.misc.ReflectUtil; /** @@ -375,6 +376,7 @@ public class ObjectInputStream } if (depth == 0) { vlist.doCallbacks(); + freeze(); } return obj; } finally { @@ -465,6 +467,7 @@ public class ObjectInputStream } if (depth == 0) { vlist.doCallbacks(); + freeze(); } return obj; } finally { @@ -2357,6 +2360,26 @@ public class ObjectInputStream } } + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); + + /** + * Performs a "freeze" action, required to adhere to final field semantics. + * + *
This method can be called unconditionally before returning the graph, + * from the topmost readObject call, since it is expected that the + * additional cost of the freeze action is negligible compared to + * reconstituting even the most simple graph. + * + *
Nested calls to readObject do not issue freeze actions because the
+ * sub-graph returned from a nested call is not guaranteed to be fully
+ * initialized yet (possible cycles).
+ */
+ private void freeze() {
+ // Issue a StoreStore|StoreLoad fence, which is at least sufficient
+ // to provide final-freeze semantics.
+ UNSAFE.storeFence();
+ }
+
/**
* Input stream with two modes: in default mode, inputs data written in the
* same format as DataOutputStream; in "block data" mode, inputs data
diff --git a/jdk/src/java.base/share/classes/java/math/BigDecimal.java b/jdk/src/java.base/share/classes/java/math/BigDecimal.java
index f4fffc871a4..2afd6e3b7a2 100644
--- a/jdk/src/java.base/share/classes/java/math/BigDecimal.java
+++ b/jdk/src/java.base/share/classes/java/math/BigDecimal.java
@@ -3740,8 +3740,8 @@ public class BigDecimal extends Number implements Comparable