# HG changeset patch # User dl # Date 1318433628 -3600 # Node ID 1b260c532b7016cdedc005e3ff0e32affc73fb61 # Parent 5a763073fa3746c3b7c9deed24984293c5529b4e 7082299: AtomicReferenceArray should ensure that array is Object[] Reviewed-by: chegar, dholmes, alanb diff -r 5a763073fa37 -r 1b260c532b70 jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java --- a/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java Fri Sep 30 18:47:53 2011 -0700 +++ b/jdk/src/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java Wed Oct 12 16:33:48 2011 +0100 @@ -34,8 +34,10 @@ */ package java.util.concurrent.atomic; + +import java.lang.reflect.Array; +import java.util.Arrays; import sun.misc.Unsafe; -import java.util.*; /** * An array of object references in which elements may be updated @@ -49,13 +51,23 @@ public class AtomicReferenceArray implements java.io.Serializable { private static final long serialVersionUID = -6209656149925076980L; - private static final Unsafe unsafe = Unsafe.getUnsafe(); - private static final int base = unsafe.arrayBaseOffset(Object[].class); + private static final Unsafe unsafe; + private static final int base; private static final int shift; - private final Object[] array; + private static final long arrayFieldOffset; + private final Object[] array; // must have exact type Object[] static { - int scale = unsafe.arrayIndexScale(Object[].class); + int scale; + try { + unsafe = Unsafe.getUnsafe(); + arrayFieldOffset = unsafe.objectFieldOffset + (AtomicReferenceArray.class.getDeclaredField("array")); + base = unsafe.arrayBaseOffset(Object[].class); + scale = unsafe.arrayIndexScale(Object[].class); + } catch (Exception e) { + throw new Error(e); + } if ((scale & (scale - 1)) != 0) throw new Error("data type scale not a power of two"); shift = 31 - Integer.numberOfLeadingZeros(scale); @@ -91,7 +103,7 @@ */ public AtomicReferenceArray(E[] array) { // Visibility guaranteed by final field guarantees - this.array = array.clone(); + this.array = Arrays.copyOf(array, array.length, Object[].class); } /** @@ -150,7 +162,7 @@ public final E getAndSet(int i, E newValue) { long offset = checkedByteOffset(i); while (true) { - E current = (E) getRaw(offset); + E current = getRaw(offset); if (compareAndSetRaw(offset, current, newValue)) return current; } @@ -196,7 +208,7 @@ * @return the String representation of the current values of array */ public String toString() { - int iMax = array.length - 1; + int iMax = array.length - 1; if (iMax == -1) return "[]"; @@ -210,4 +222,19 @@ } } + /** + * Reconstitutes the instance from a stream (that is, deserializes it). + * @param s the stream + */ + private void readObject(java.io.ObjectInputStream s) + throws java.io.IOException, ClassNotFoundException { + // Note: This must be changed if any additional fields are defined + Object a = s.readFields().get("array", null); + if (a == null || !a.getClass().isArray()) + throw new java.io.InvalidObjectException("Not array type"); + if (a.getClass() != Object[].class) + a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class); + unsafe.putObjectVolatile(this, arrayFieldOffset, a); + } + }