提交 129aa67a 编写于 作者: R robm

8140587: Atomic*FieldUpdaters should use Class.isInstance instead of direct class check

Reviewed-by: martin
上级 711ac304
...@@ -34,14 +34,14 @@ ...@@ -34,14 +34,14 @@
*/ */
package java.util.concurrent.atomic; package java.util.concurrent.atomic;
import java.util.function.IntUnaryOperator;
import java.util.function.IntBinaryOperator;
import sun.misc.Unsafe;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException; import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.function.IntBinaryOperator;
import java.util.function.IntUnaryOperator;
import sun.reflect.CallerSensitive; import sun.reflect.CallerSensitive;
import sun.reflect.Reflection; import sun.reflect.Reflection;
...@@ -363,14 +363,19 @@ public abstract class AtomicIntegerFieldUpdater<T> { ...@@ -363,14 +363,19 @@ public abstract class AtomicIntegerFieldUpdater<T> {
} }
/** /**
* Standard hotspot implementation using intrinsics * Standard hotspot implementation using intrinsics.
*/ */
private static class AtomicIntegerFieldUpdaterImpl<T> private static final class AtomicIntegerFieldUpdaterImpl<T>
extends AtomicIntegerFieldUpdater<T> { extends AtomicIntegerFieldUpdater<T> {
private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private final long offset; private final long offset;
private final Class<T> tclass; /**
* if field is protected, the subclass constructing updater, else
* the same as tclass
*/
private final Class<?> cclass; private final Class<?> cclass;
/** class holding the field */
private final Class<T> tclass;
AtomicIntegerFieldUpdaterImpl(final Class<T> tclass, AtomicIntegerFieldUpdaterImpl(final Class<T> tclass,
final String fieldName, final String fieldName,
...@@ -391,7 +396,7 @@ public abstract class AtomicIntegerFieldUpdater<T> { ...@@ -391,7 +396,7 @@ public abstract class AtomicIntegerFieldUpdater<T> {
ClassLoader ccl = caller.getClassLoader(); ClassLoader ccl = caller.getClassLoader();
if ((ccl != null) && (ccl != cl) && if ((ccl != null) && (ccl != cl) &&
((cl == null) || !isAncestor(cl, ccl))) { ((cl == null) || !isAncestor(cl, ccl))) {
sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
} }
} catch (PrivilegedActionException pae) { } catch (PrivilegedActionException pae) {
throw new RuntimeException(pae.getException()); throw new RuntimeException(pae.getException());
...@@ -399,17 +404,15 @@ public abstract class AtomicIntegerFieldUpdater<T> { ...@@ -399,17 +404,15 @@ public abstract class AtomicIntegerFieldUpdater<T> {
throw new RuntimeException(ex); throw new RuntimeException(ex);
} }
Class<?> fieldt = field.getType(); if (field.getType() != int.class)
if (fieldt != int.class)
throw new IllegalArgumentException("Must be integer type"); throw new IllegalArgumentException("Must be integer type");
if (!Modifier.isVolatile(modifiers)) if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type"); throw new IllegalArgumentException("Must be volatile type");
this.cclass = (Modifier.isProtected(modifiers) && this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
caller != tclass) ? caller : null;
this.tclass = tclass; this.tclass = tclass;
offset = unsafe.objectFieldOffset(field); this.offset = U.objectFieldOffset(field);
} }
/** /**
...@@ -428,81 +431,87 @@ public abstract class AtomicIntegerFieldUpdater<T> { ...@@ -428,81 +431,87 @@ public abstract class AtomicIntegerFieldUpdater<T> {
return false; return false;
} }
private void fullCheck(T obj) { /**
if (!tclass.isInstance(obj)) * Checks that target argument is instance of cclass. On
* failure, throws cause.
*/
private final void accessCheck(T obj) {
if (!cclass.isInstance(obj))
throwAccessCheckException(obj);
}
/**
* Throws access exception if accessCheck failed due to
* protected access, else ClassCastException.
*/
private final void throwAccessCheckException(T obj) {
if (cclass == tclass)
throw new ClassCastException(); throw new ClassCastException();
if (cclass != null) else
ensureProtectedAccess(obj); throw new RuntimeException(
new IllegalAccessException(
"Class " +
cclass.getName() +
" can not access a protected member of class " +
tclass.getName() +
" using an instance of " +
obj.getClass().getName()));
} }
public boolean compareAndSet(T obj, int expect, int update) { public final boolean compareAndSet(T obj, int expect, int update) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); accessCheck(obj);
return unsafe.compareAndSwapInt(obj, offset, expect, update); return U.compareAndSwapInt(obj, offset, expect, update);
} }
public boolean weakCompareAndSet(T obj, int expect, int update) { public final boolean weakCompareAndSet(T obj, int expect, int update) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); accessCheck(obj);
return unsafe.compareAndSwapInt(obj, offset, expect, update); return U.compareAndSwapInt(obj, offset, expect, update);
} }
public void set(T obj, int newValue) { public final void set(T obj, int newValue) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); accessCheck(obj);
unsafe.putIntVolatile(obj, offset, newValue); U.putIntVolatile(obj, offset, newValue);
} }
public void lazySet(T obj, int newValue) { public final void lazySet(T obj, int newValue) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); accessCheck(obj);
unsafe.putOrderedInt(obj, offset, newValue); U.putOrderedInt(obj, offset, newValue);
} }
public final int get(T obj) { public final int get(T obj) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); accessCheck(obj);
return unsafe.getIntVolatile(obj, offset); return U.getIntVolatile(obj, offset);
} }
public int getAndSet(T obj, int newValue) { public final int getAndSet(T obj, int newValue) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); accessCheck(obj);
return unsafe.getAndSetInt(obj, offset, newValue); return U.getAndSetInt(obj, offset, newValue);
} }
public int getAndIncrement(T obj) { public final int getAndAdd(T obj, int delta) {
return getAndAdd(obj, 1); accessCheck(obj);
return U.getAndAddInt(obj, offset, delta);
} }
public int getAndDecrement(T obj) { public final int getAndIncrement(T obj) {
return getAndAdd(obj, -1); return getAndAdd(obj, 1);
} }
public int getAndAdd(T obj, int delta) { public final int getAndDecrement(T obj) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); return getAndAdd(obj, -1);
return unsafe.getAndAddInt(obj, offset, delta);
} }
public int incrementAndGet(T obj) { public final int incrementAndGet(T obj) {
return getAndAdd(obj, 1) + 1; return getAndAdd(obj, 1) + 1;
} }
public int decrementAndGet(T obj) { public final int decrementAndGet(T obj) {
return getAndAdd(obj, -1) - 1; return getAndAdd(obj, -1) - 1;
} }
public int addAndGet(T obj, int delta) { public final int addAndGet(T obj, int delta) {
return getAndAdd(obj, delta) + delta; return getAndAdd(obj, delta) + delta;
} }
private void ensureProtectedAccess(T obj) {
if (cclass.isInstance(obj)) {
return;
}
throw new RuntimeException(
new IllegalAccessException("Class " +
cclass.getName() +
" can not access a protected member of class " +
tclass.getName() +
" using an instance of " +
obj.getClass().getName()
)
);
}
} }
} }
...@@ -34,14 +34,14 @@ ...@@ -34,14 +34,14 @@
*/ */
package java.util.concurrent.atomic; package java.util.concurrent.atomic;
import java.util.function.LongUnaryOperator;
import java.util.function.LongBinaryOperator;
import sun.misc.Unsafe;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException; import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.function.LongBinaryOperator;
import java.util.function.LongUnaryOperator;
import sun.reflect.CallerSensitive; import sun.reflect.CallerSensitive;
import sun.reflect.Reflection; import sun.reflect.Reflection;
...@@ -365,11 +365,16 @@ public abstract class AtomicLongFieldUpdater<T> { ...@@ -365,11 +365,16 @@ public abstract class AtomicLongFieldUpdater<T> {
return next; return next;
} }
private static class CASUpdater<T> extends AtomicLongFieldUpdater<T> { private static final class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private final long offset; private final long offset;
private final Class<T> tclass; /**
* if field is protected, the subclass constructing updater, else
* the same as tclass
*/
private final Class<?> cclass; private final Class<?> cclass;
/** class holding the field */
private final Class<T> tclass;
CASUpdater(final Class<T> tclass, final String fieldName, CASUpdater(final Class<T> tclass, final String fieldName,
final Class<?> caller) { final Class<?> caller) {
...@@ -389,7 +394,7 @@ public abstract class AtomicLongFieldUpdater<T> { ...@@ -389,7 +394,7 @@ public abstract class AtomicLongFieldUpdater<T> {
ClassLoader ccl = caller.getClassLoader(); ClassLoader ccl = caller.getClassLoader();
if ((ccl != null) && (ccl != cl) && if ((ccl != null) && (ccl != cl) &&
((cl == null) || !isAncestor(cl, ccl))) { ((cl == null) || !isAncestor(cl, ccl))) {
sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
} }
} catch (PrivilegedActionException pae) { } catch (PrivilegedActionException pae) {
throw new RuntimeException(pae.getException()); throw new RuntimeException(pae.getException());
...@@ -397,103 +402,110 @@ public abstract class AtomicLongFieldUpdater<T> { ...@@ -397,103 +402,110 @@ public abstract class AtomicLongFieldUpdater<T> {
throw new RuntimeException(ex); throw new RuntimeException(ex);
} }
Class<?> fieldt = field.getType(); if (field.getType() != long.class)
if (fieldt != long.class)
throw new IllegalArgumentException("Must be long type"); throw new IllegalArgumentException("Must be long type");
if (!Modifier.isVolatile(modifiers)) if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type"); throw new IllegalArgumentException("Must be volatile type");
this.cclass = (Modifier.isProtected(modifiers) && this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
caller != tclass) ? caller : null;
this.tclass = tclass; this.tclass = tclass;
offset = unsafe.objectFieldOffset(field); this.offset = U.objectFieldOffset(field);
}
/**
* Checks that target argument is instance of cclass. On
* failure, throws cause.
*/
private final void accessCheck(T obj) {
if (!cclass.isInstance(obj))
throwAccessCheckException(obj);
} }
private void fullCheck(T obj) { /**
if (!tclass.isInstance(obj)) * Throws access exception if accessCheck failed due to
* protected access, else ClassCastException.
*/
private final void throwAccessCheckException(T obj) {
if (cclass == tclass)
throw new ClassCastException(); throw new ClassCastException();
if (cclass != null) else
ensureProtectedAccess(obj); throw new RuntimeException(
new IllegalAccessException(
"Class " +
cclass.getName() +
" can not access a protected member of class " +
tclass.getName() +
" using an instance of " +
obj.getClass().getName()));
} }
public boolean compareAndSet(T obj, long expect, long update) { public final boolean compareAndSet(T obj, long expect, long update) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); accessCheck(obj);
return unsafe.compareAndSwapLong(obj, offset, expect, update); return U.compareAndSwapLong(obj, offset, expect, update);
} }
public boolean weakCompareAndSet(T obj, long expect, long update) { public final boolean weakCompareAndSet(T obj, long expect, long update) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); accessCheck(obj);
return unsafe.compareAndSwapLong(obj, offset, expect, update); return U.compareAndSwapLong(obj, offset, expect, update);
} }
public void set(T obj, long newValue) { public final void set(T obj, long newValue) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); accessCheck(obj);
unsafe.putLongVolatile(obj, offset, newValue); U.putLongVolatile(obj, offset, newValue);
} }
public void lazySet(T obj, long newValue) { public final void lazySet(T obj, long newValue) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); accessCheck(obj);
unsafe.putOrderedLong(obj, offset, newValue); U.putOrderedLong(obj, offset, newValue);
} }
public long get(T obj) { public final long get(T obj) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); accessCheck(obj);
return unsafe.getLongVolatile(obj, offset); return U.getLongVolatile(obj, offset);
} }
public long getAndSet(T obj, long newValue) { public final long getAndSet(T obj, long newValue) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); accessCheck(obj);
return unsafe.getAndSetLong(obj, offset, newValue); return U.getAndSetLong(obj, offset, newValue);
} }
public long getAndIncrement(T obj) { public final long getAndAdd(T obj, long delta) {
return getAndAdd(obj, 1); accessCheck(obj);
return U.getAndAddLong(obj, offset, delta);
} }
public long getAndDecrement(T obj) { public final long getAndIncrement(T obj) {
return getAndAdd(obj, -1); return getAndAdd(obj, 1);
} }
public long getAndAdd(T obj, long delta) { public final long getAndDecrement(T obj) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); return getAndAdd(obj, -1);
return unsafe.getAndAddLong(obj, offset, delta);
} }
public long incrementAndGet(T obj) { public final long incrementAndGet(T obj) {
return getAndAdd(obj, 1) + 1; return getAndAdd(obj, 1) + 1;
} }
public long decrementAndGet(T obj) { public final long decrementAndGet(T obj) {
return getAndAdd(obj, -1) - 1; return getAndAdd(obj, -1) - 1;
} }
public long addAndGet(T obj, long delta) { public final long addAndGet(T obj, long delta) {
return getAndAdd(obj, delta) + delta; return getAndAdd(obj, delta) + delta;
} }
private void ensureProtectedAccess(T obj) {
if (cclass.isInstance(obj)) {
return;
}
throw new RuntimeException(
new IllegalAccessException("Class " +
cclass.getName() +
" can not access a protected member of class " +
tclass.getName() +
" using an instance of " +
obj.getClass().getName()
)
);
}
} }
private static final class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
private static class LockedUpdater<T> extends AtomicLongFieldUpdater<T> { private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private static final Unsafe unsafe = Unsafe.getUnsafe();
private final long offset; private final long offset;
private final Class<T> tclass; /**
* if field is protected, the subclass constructing updater, else
* the same as tclass
*/
private final Class<?> cclass; private final Class<?> cclass;
/** class holding the field */
private final Class<T> tclass;
LockedUpdater(final Class<T> tclass, final String fieldName, LockedUpdater(final Class<T> tclass, final String fieldName,
final Class<?> caller) { final Class<?> caller) {
...@@ -513,7 +525,7 @@ public abstract class AtomicLongFieldUpdater<T> { ...@@ -513,7 +525,7 @@ public abstract class AtomicLongFieldUpdater<T> {
ClassLoader ccl = caller.getClassLoader(); ClassLoader ccl = caller.getClassLoader();
if ((ccl != null) && (ccl != cl) && if ((ccl != null) && (ccl != cl) &&
((cl == null) || !isAncestor(cl, ccl))) { ((cl == null) || !isAncestor(cl, ccl))) {
sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
} }
} catch (PrivilegedActionException pae) { } catch (PrivilegedActionException pae) {
throw new RuntimeException(pae.getException()); throw new RuntimeException(pae.getException());
...@@ -521,72 +533,75 @@ public abstract class AtomicLongFieldUpdater<T> { ...@@ -521,72 +533,75 @@ public abstract class AtomicLongFieldUpdater<T> {
throw new RuntimeException(ex); throw new RuntimeException(ex);
} }
Class<?> fieldt = field.getType(); if (field.getType() != long.class)
if (fieldt != long.class)
throw new IllegalArgumentException("Must be long type"); throw new IllegalArgumentException("Must be long type");
if (!Modifier.isVolatile(modifiers)) if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type"); throw new IllegalArgumentException("Must be volatile type");
this.cclass = (Modifier.isProtected(modifiers) && this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
caller != tclass) ? caller : null;
this.tclass = tclass; this.tclass = tclass;
offset = unsafe.objectFieldOffset(field); this.offset = U.objectFieldOffset(field);
} }
private void fullCheck(T obj) { /**
if (!tclass.isInstance(obj)) * Checks that target argument is instance of cclass. On
throw new ClassCastException(); * failure, throws cause.
if (cclass != null) */
ensureProtectedAccess(obj); private final void accessCheck(T obj) {
if (!cclass.isInstance(obj))
throw accessCheckException(obj);
}
/**
* Returns access exception if accessCheck failed due to
* protected access, else ClassCastException.
*/
private final RuntimeException accessCheckException(T obj) {
if (cclass == tclass)
return new ClassCastException();
else
return new RuntimeException(
new IllegalAccessException(
"Class " +
cclass.getName() +
" can not access a protected member of class " +
tclass.getName() +
" using an instance of " +
obj.getClass().getName()));
} }
public boolean compareAndSet(T obj, long expect, long update) { public final boolean compareAndSet(T obj, long expect, long update) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); accessCheck(obj);
synchronized (this) { synchronized (this) {
long v = unsafe.getLong(obj, offset); long v = U.getLong(obj, offset);
if (v != expect) if (v != expect)
return false; return false;
unsafe.putLong(obj, offset, update); U.putLong(obj, offset, update);
return true; return true;
} }
} }
public boolean weakCompareAndSet(T obj, long expect, long update) { public final boolean weakCompareAndSet(T obj, long expect, long update) {
return compareAndSet(obj, expect, update); return compareAndSet(obj, expect, update);
} }
public void set(T obj, long newValue) { public final void set(T obj, long newValue) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); accessCheck(obj);
synchronized (this) { synchronized (this) {
unsafe.putLong(obj, offset, newValue); U.putLong(obj, offset, newValue);
} }
} }
public void lazySet(T obj, long newValue) { public final void lazySet(T obj, long newValue) {
set(obj, newValue); set(obj, newValue);
} }
public long get(T obj) { public final long get(T obj) {
if (obj == null || obj.getClass() != tclass || cclass != null) fullCheck(obj); accessCheck(obj);
synchronized (this) { synchronized (this) {
return unsafe.getLong(obj, offset); return U.getLong(obj, offset);
}
}
private void ensureProtectedAccess(T obj) {
if (cclass.isInstance(obj)) {
return;
} }
throw new RuntimeException(
new IllegalAccessException("Class " +
cclass.getName() +
" can not access a protected member of class " +
tclass.getName() +
" using an instance of " +
obj.getClass().getName()
)
);
} }
} }
...@@ -595,7 +610,7 @@ public abstract class AtomicLongFieldUpdater<T> { ...@@ -595,7 +610,7 @@ public abstract class AtomicLongFieldUpdater<T> {
* classloader's delegation chain. * classloader's delegation chain.
* Equivalent to the inaccessible: first.isAncestor(second). * Equivalent to the inaccessible: first.isAncestor(second).
*/ */
private static boolean isAncestor(ClassLoader first, ClassLoader second) { static boolean isAncestor(ClassLoader first, ClassLoader second) {
ClassLoader acl = first; ClassLoader acl = first;
do { do {
acl = acl.getParent(); acl = acl.getParent();
......
...@@ -34,14 +34,14 @@ ...@@ -34,14 +34,14 @@
*/ */
package java.util.concurrent.atomic; package java.util.concurrent.atomic;
import java.util.function.UnaryOperator;
import java.util.function.BinaryOperator;
import sun.misc.Unsafe;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.security.PrivilegedActionException; import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.function.BinaryOperator;
import java.util.function.UnaryOperator;
import sun.reflect.CallerSensitive; import sun.reflect.CallerSensitive;
import sun.reflect.Reflection; import sun.reflect.Reflection;
...@@ -53,7 +53,7 @@ import sun.reflect.Reflection; ...@@ -53,7 +53,7 @@ import sun.reflect.Reflection;
* independently subject to atomic updates. For example, a tree node * independently subject to atomic updates. For example, a tree node
* might be declared as * might be declared as
* *
* <pre> {@code * <pre> {@code
* class Node { * class Node {
* private volatile Node left, right; * private volatile Node left, right;
* *
...@@ -62,7 +62,7 @@ import sun.reflect.Reflection; ...@@ -62,7 +62,7 @@ import sun.reflect.Reflection;
* private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater = * private static AtomicReferenceFieldUpdater<Node, Node> rightUpdater =
* AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right"); * AtomicReferenceFieldUpdater.newUpdater(Node.class, Node.class, "right");
* *
* Node getLeft() { return left; } * Node getLeft() { return left; }
* boolean compareAndSetLeft(Node expect, Node update) { * boolean compareAndSetLeft(Node expect, Node update) {
* return leftUpdater.compareAndSet(this, expect, update); * return leftUpdater.compareAndSet(this, expect, update);
* } * }
...@@ -284,11 +284,17 @@ public abstract class AtomicReferenceFieldUpdater<T,V> { ...@@ -284,11 +284,17 @@ public abstract class AtomicReferenceFieldUpdater<T,V> {
private static final class AtomicReferenceFieldUpdaterImpl<T,V> private static final class AtomicReferenceFieldUpdaterImpl<T,V>
extends AtomicReferenceFieldUpdater<T,V> { extends AtomicReferenceFieldUpdater<T,V> {
private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
private final long offset; private final long offset;
/**
* if field is protected, the subclass constructing updater, else
* the same as tclass
*/
private final Class<?> cclass;
/** class holding the field */
private final Class<T> tclass; private final Class<T> tclass;
/** field value type */
private final Class<V> vclass; private final Class<V> vclass;
private final Class<?> cclass;
/* /*
* Internal type checks within all update methods contain * Internal type checks within all update methods contain
...@@ -323,7 +329,7 @@ public abstract class AtomicReferenceFieldUpdater<T,V> { ...@@ -323,7 +329,7 @@ public abstract class AtomicReferenceFieldUpdater<T,V> {
ClassLoader ccl = caller.getClassLoader(); ClassLoader ccl = caller.getClassLoader();
if ((ccl != null) && (ccl != cl) && if ((ccl != null) && (ccl != cl) &&
((cl == null) || !isAncestor(cl, ccl))) { ((cl == null) || !isAncestor(cl, ccl))) {
sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass); sun.reflect.misc.ReflectUtil.checkPackageAccess(tclass);
} }
fieldClass = field.getType(); fieldClass = field.getType();
} catch (PrivilegedActionException pae) { } catch (PrivilegedActionException pae) {
...@@ -340,14 +346,10 @@ public abstract class AtomicReferenceFieldUpdater<T,V> { ...@@ -340,14 +346,10 @@ public abstract class AtomicReferenceFieldUpdater<T,V> {
if (!Modifier.isVolatile(modifiers)) if (!Modifier.isVolatile(modifiers))
throw new IllegalArgumentException("Must be volatile type"); throw new IllegalArgumentException("Must be volatile type");
this.cclass = (Modifier.isProtected(modifiers) && this.cclass = (Modifier.isProtected(modifiers)) ? caller : tclass;
caller != tclass) ? caller : null;
this.tclass = tclass; this.tclass = tclass;
if (vclass == Object.class) this.vclass = vclass;
this.vclass = null; this.offset = U.objectFieldOffset(field);
else
this.vclass = vclass;
offset = unsafe.objectFieldOffset(field);
} }
/** /**
...@@ -366,83 +368,78 @@ public abstract class AtomicReferenceFieldUpdater<T,V> { ...@@ -366,83 +368,78 @@ public abstract class AtomicReferenceFieldUpdater<T,V> {
return false; return false;
} }
void targetCheck(T obj) { /**
if (!tclass.isInstance(obj)) * Checks that target argument is instance of cclass. On
throw new ClassCastException(); * failure, throws cause.
if (cclass != null) */
ensureProtectedAccess(obj); private final void accessCheck(T obj) {
if (!cclass.isInstance(obj))
throwAccessCheckException(obj);
} }
void updateCheck(T obj, V update) { /**
if (!tclass.isInstance(obj) || * Throws access exception if accessCheck failed due to
(update != null && vclass != null && !vclass.isInstance(update))) * protected access, else ClassCastException.
*/
private final void throwAccessCheckException(T obj) {
if (cclass == tclass)
throw new ClassCastException(); throw new ClassCastException();
if (cclass != null) else
ensureProtectedAccess(obj); throw new RuntimeException(
new IllegalAccessException(
"Class " +
cclass.getName() +
" can not access a protected member of class " +
tclass.getName() +
" using an instance of " +
obj.getClass().getName()));
} }
public boolean compareAndSet(T obj, V expect, V update) { private final void valueCheck(V v) {
if (obj == null || obj.getClass() != tclass || cclass != null || if (v != null && !(vclass.isInstance(v)))
(update != null && vclass != null && throwCCE();
vclass != update.getClass()))
updateCheck(obj, update);
return unsafe.compareAndSwapObject(obj, offset, expect, update);
} }
public boolean weakCompareAndSet(T obj, V expect, V update) { static void throwCCE() {
// same implementation as strong form for now throw new ClassCastException();
if (obj == null || obj.getClass() != tclass || cclass != null ||
(update != null && vclass != null &&
vclass != update.getClass()))
updateCheck(obj, update);
return unsafe.compareAndSwapObject(obj, offset, expect, update);
} }
public void set(T obj, V newValue) { public final boolean compareAndSet(T obj, V expect, V update) {
if (obj == null || obj.getClass() != tclass || cclass != null || accessCheck(obj);
(newValue != null && vclass != null && valueCheck(update);
vclass != newValue.getClass())) return U.compareAndSwapObject(obj, offset, expect, update);
updateCheck(obj, newValue);
unsafe.putObjectVolatile(obj, offset, newValue);
} }
public void lazySet(T obj, V newValue) { public final boolean weakCompareAndSet(T obj, V expect, V update) {
if (obj == null || obj.getClass() != tclass || cclass != null || // same implementation as strong form for now
(newValue != null && vclass != null && accessCheck(obj);
vclass != newValue.getClass())) valueCheck(update);
updateCheck(obj, newValue); return U.compareAndSwapObject(obj, offset, expect, update);
unsafe.putOrderedObject(obj, offset, newValue);
} }
@SuppressWarnings("unchecked") public final void set(T obj, V newValue) {
public V get(T obj) { accessCheck(obj);
if (obj == null || obj.getClass() != tclass || cclass != null) valueCheck(newValue);
targetCheck(obj); U.putObjectVolatile(obj, offset, newValue);
return (V)unsafe.getObjectVolatile(obj, offset); }
public final void lazySet(T obj, V newValue) {
accessCheck(obj);
valueCheck(newValue);
U.putOrderedObject(obj, offset, newValue);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public V getAndSet(T obj, V newValue) { public final V get(T obj) {
if (obj == null || obj.getClass() != tclass || cclass != null || accessCheck(obj);
(newValue != null && vclass != null && return (V)U.getObjectVolatile(obj, offset);
vclass != newValue.getClass()))
updateCheck(obj, newValue);
return (V)unsafe.getAndSetObject(obj, offset, newValue);
} }
private void ensureProtectedAccess(T obj) { @SuppressWarnings("unchecked")
if (cclass.isInstance(obj)) { public final V getAndSet(T obj, V newValue) {
return; accessCheck(obj);
} valueCheck(newValue);
throw new RuntimeException( return (V)U.getAndSetObject(obj, offset, newValue);
new IllegalAccessException("Class " +
cclass.getName() +
" can not access a protected member of class " +
tclass.getName() +
" using an instance of " +
obj.getClass().getName()
)
);
} }
} }
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册