7082299: AtomicReferenceArray should ensure that array is Object[]
Reviewed-by: chegar, dholmes, alanb
--- 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<E> 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);
+ }
+
}