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:
Chris Hegarty 2015-02-27 11:45:07 +00:00
parent 90a23fca14
commit dc378de91b
3 changed files with 28 additions and 5 deletions

View File

@ -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.
*
* <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
* same format as DataOutputStream; in "block data" mode, inputs data

View File

@ -3740,8 +3740,8 @@ public class BigDecimal extends Number implements Comparable<BigDecimal> {
throw new ExceptionInInitializerError(ex);
}
}
static void setIntCompactVolatile(BigDecimal bd, long val) {
unsafe.putLongVolatile(bd, intCompactOffset, val);
static void setIntCompact(BigDecimal bd, long val) {
unsafe.putLong(bd, intCompactOffset, 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);
// [all values of scale are now allowed]
}
UnsafeHolder.setIntCompactVolatile(this, compactValFor(intVal));
UnsafeHolder.setIntCompact(this, compactValFor(intVal));
}
/**

View File

@ -4368,11 +4368,11 @@ public class BigInteger extends Number implements Comparable<BigInteger> {
}
static void putSign(BigInteger bi, int sign) {
unsafe.putIntVolatile(bi, signumOffset, sign);
unsafe.putInt(bi, signumOffset, sign);
}
static void putMag(BigInteger bi, int[] magnitude) {
unsafe.putObjectVolatile(bi, magOffset, magnitude);
unsafe.putObject(bi, magOffset, magnitude);
}
}