8074022: Serialization should issue a freeze action after reconstituting a graph that contains objects with final fields
Reviewed-by: dholmes, plevart, psandoz
This commit is contained in:
parent
90a23fca14
commit
dc378de91b
@ -40,6 +40,7 @@ import java.util.HashMap;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import static java.io.ObjectStreamClass.processQueue;
|
import static java.io.ObjectStreamClass.processQueue;
|
||||||
|
import sun.misc.Unsafe;
|
||||||
import sun.reflect.misc.ReflectUtil;
|
import sun.reflect.misc.ReflectUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -375,6 +376,7 @@ public class ObjectInputStream
|
|||||||
}
|
}
|
||||||
if (depth == 0) {
|
if (depth == 0) {
|
||||||
vlist.doCallbacks();
|
vlist.doCallbacks();
|
||||||
|
freeze();
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
} finally {
|
} finally {
|
||||||
@ -465,6 +467,7 @@ public class ObjectInputStream
|
|||||||
}
|
}
|
||||||
if (depth == 0) {
|
if (depth == 0) {
|
||||||
vlist.doCallbacks();
|
vlist.doCallbacks();
|
||||||
|
freeze();
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
} finally {
|
} 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.
|
||||||
|
*
|
||||||
|
* <p> 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.
|
||||||
|
*
|
||||||
|
* <p> 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
|
* Input stream with two modes: in default mode, inputs data written in the
|
||||||
* same format as DataOutputStream; in "block data" mode, inputs data
|
* same format as DataOutputStream; in "block data" mode, inputs data
|
||||||
|
@ -3740,8 +3740,8 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
|||||||
throw new ExceptionInInitializerError(ex);
|
throw new ExceptionInInitializerError(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void setIntCompactVolatile(BigDecimal bd, long val) {
|
static void setIntCompact(BigDecimal bd, long val) {
|
||||||
unsafe.putLongVolatile(bd, intCompactOffset, val);
|
unsafe.putLong(bd, intCompactOffset, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setIntValVolatile(BigDecimal bd, BigInteger val) {
|
static void setIntValVolatile(BigDecimal bd, BigInteger val) {
|
||||||
@ -3765,7 +3765,7 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
|
|||||||
throw new java.io.StreamCorruptedException(message);
|
throw new java.io.StreamCorruptedException(message);
|
||||||
// [all values of scale are now allowed]
|
// [all values of scale are now allowed]
|
||||||
}
|
}
|
||||||
UnsafeHolder.setIntCompactVolatile(this, compactValFor(intVal));
|
UnsafeHolder.setIntCompact(this, compactValFor(intVal));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4368,11 +4368,11 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void putSign(BigInteger bi, int sign) {
|
static void putSign(BigInteger bi, int sign) {
|
||||||
unsafe.putIntVolatile(bi, signumOffset, sign);
|
unsafe.putInt(bi, signumOffset, sign);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void putMag(BigInteger bi, int[] magnitude) {
|
static void putMag(BigInteger bi, int[] magnitude) {
|
||||||
unsafe.putObjectVolatile(bi, magOffset, magnitude);
|
unsafe.putObject(bi, magOffset, magnitude);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user