mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-09 14:38:42 +00:00
7017493: ConcurrentLinkedDeque: Unexpected initialization order can lead to crash due to use of Unsafe
Reviewed-by: chegar
This commit is contained in:
parent
dd0e38d73a
commit
ad3d04a30c
@ -272,13 +272,6 @@ public class ConcurrentLinkedDeque<E>
|
||||
|
||||
private static final Node<Object> PREV_TERMINATOR, NEXT_TERMINATOR;
|
||||
|
||||
static {
|
||||
PREV_TERMINATOR = new Node<Object>(null);
|
||||
PREV_TERMINATOR.next = PREV_TERMINATOR;
|
||||
NEXT_TERMINATOR = new Node<Object>(null);
|
||||
NEXT_TERMINATOR.prev = NEXT_TERMINATOR;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Node<E> prevTerminator() {
|
||||
return (Node<E>) PREV_TERMINATOR;
|
||||
@ -294,6 +287,9 @@ public class ConcurrentLinkedDeque<E>
|
||||
volatile E item;
|
||||
volatile Node<E> next;
|
||||
|
||||
Node() { // default constructor for NEXT_TERMINATOR, PREV_TERMINATOR
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new node. Uses relaxed write because item can
|
||||
* only be seen after publication via casNext or casPrev.
|
||||
@ -324,14 +320,25 @@ public class ConcurrentLinkedDeque<E>
|
||||
|
||||
// Unsafe mechanics
|
||||
|
||||
private static final sun.misc.Unsafe UNSAFE =
|
||||
sun.misc.Unsafe.getUnsafe();
|
||||
private static final long prevOffset =
|
||||
objectFieldOffset(UNSAFE, "prev", Node.class);
|
||||
private static final long itemOffset =
|
||||
objectFieldOffset(UNSAFE, "item", Node.class);
|
||||
private static final long nextOffset =
|
||||
objectFieldOffset(UNSAFE, "next", Node.class);
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long prevOffset;
|
||||
private static final long itemOffset;
|
||||
private static final long nextOffset;
|
||||
|
||||
static {
|
||||
try {
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class k = Node.class;
|
||||
prevOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("prev"));
|
||||
itemOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("item"));
|
||||
nextOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("next"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1422,14 +1429,6 @@ public class ConcurrentLinkedDeque<E>
|
||||
initHeadTail(h, t);
|
||||
}
|
||||
|
||||
// Unsafe mechanics
|
||||
|
||||
private static final sun.misc.Unsafe UNSAFE =
|
||||
sun.misc.Unsafe.getUnsafe();
|
||||
private static final long headOffset =
|
||||
objectFieldOffset(UNSAFE, "head", ConcurrentLinkedDeque.class);
|
||||
private static final long tailOffset =
|
||||
objectFieldOffset(UNSAFE, "tail", ConcurrentLinkedDeque.class);
|
||||
|
||||
private boolean casHead(Node<E> cmp, Node<E> val) {
|
||||
return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
|
||||
@ -1439,15 +1438,25 @@ public class ConcurrentLinkedDeque<E>
|
||||
return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
|
||||
}
|
||||
|
||||
static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
|
||||
String field, Class<?> klazz) {
|
||||
// Unsafe mechanics
|
||||
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long headOffset;
|
||||
private static final long tailOffset;
|
||||
static {
|
||||
PREV_TERMINATOR = new Node<Object>();
|
||||
PREV_TERMINATOR.next = PREV_TERMINATOR;
|
||||
NEXT_TERMINATOR = new Node<Object>();
|
||||
NEXT_TERMINATOR.prev = NEXT_TERMINATOR;
|
||||
try {
|
||||
return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
|
||||
} catch (NoSuchFieldException e) {
|
||||
// Convert Exception to corresponding Error
|
||||
NoSuchFieldError error = new NoSuchFieldError(field);
|
||||
error.initCause(e);
|
||||
throw error;
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class k = ConcurrentLinkedDeque.class;
|
||||
headOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("head"));
|
||||
tailOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("tail"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -194,12 +194,22 @@ public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
|
||||
|
||||
// Unsafe mechanics
|
||||
|
||||
private static final sun.misc.Unsafe UNSAFE =
|
||||
sun.misc.Unsafe.getUnsafe();
|
||||
private static final long nextOffset =
|
||||
objectFieldOffset(UNSAFE, "next", Node.class);
|
||||
private static final long itemOffset =
|
||||
objectFieldOffset(UNSAFE, "item", Node.class);
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long itemOffset;
|
||||
private static final long nextOffset;
|
||||
|
||||
static {
|
||||
try {
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class k = Node.class;
|
||||
itemOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("item"));
|
||||
nextOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("next"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -790,14 +800,6 @@ public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
|
||||
throw new NullPointerException();
|
||||
}
|
||||
|
||||
// Unsafe mechanics
|
||||
|
||||
private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
private static final long headOffset =
|
||||
objectFieldOffset(UNSAFE, "head", ConcurrentLinkedQueue.class);
|
||||
private static final long tailOffset =
|
||||
objectFieldOffset(UNSAFE, "tail", ConcurrentLinkedQueue.class);
|
||||
|
||||
private boolean casTail(Node<E> cmp, Node<E> val) {
|
||||
return UNSAFE.compareAndSwapObject(this, tailOffset, cmp, val);
|
||||
}
|
||||
@ -806,15 +808,21 @@ public class ConcurrentLinkedQueue<E> extends AbstractQueue<E>
|
||||
return UNSAFE.compareAndSwapObject(this, headOffset, cmp, val);
|
||||
}
|
||||
|
||||
static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
|
||||
String field, Class<?> klazz) {
|
||||
// Unsafe mechanics
|
||||
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long headOffset;
|
||||
private static final long tailOffset;
|
||||
static {
|
||||
try {
|
||||
return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
|
||||
} catch (NoSuchFieldException e) {
|
||||
// Convert Exception to corresponding Error
|
||||
NoSuchFieldError error = new NoSuchFieldError(field);
|
||||
error.initCause(e);
|
||||
throw error;
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class k = ConcurrentLinkedQueue.class;
|
||||
headOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("head"));
|
||||
tailOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("tail"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -507,13 +507,24 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
|
||||
return new AbstractMap.SimpleImmutableEntry<K,V>(key, v);
|
||||
}
|
||||
|
||||
// Unsafe mechanics
|
||||
private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
private static final long valueOffset =
|
||||
objectFieldOffset(UNSAFE, "value", Node.class);
|
||||
private static final long nextOffset =
|
||||
objectFieldOffset(UNSAFE, "next", Node.class);
|
||||
// UNSAFE mechanics
|
||||
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long valueOffset;
|
||||
private static final long nextOffset;
|
||||
|
||||
static {
|
||||
try {
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class k = Node.class;
|
||||
valueOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("value"));
|
||||
nextOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("next"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------- Indexing -------------- */
|
||||
@ -580,10 +591,18 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
|
||||
}
|
||||
|
||||
// Unsafe mechanics
|
||||
private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
private static final long rightOffset =
|
||||
objectFieldOffset(UNSAFE, "right", Index.class);
|
||||
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long rightOffset;
|
||||
static {
|
||||
try {
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class k = Index.class;
|
||||
rightOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("right"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------- Head nodes -------------- */
|
||||
@ -3082,20 +3101,16 @@ public class ConcurrentSkipListMap<K,V> extends AbstractMap<K,V>
|
||||
}
|
||||
|
||||
// Unsafe mechanics
|
||||
private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
private static final long headOffset =
|
||||
objectFieldOffset(UNSAFE, "head", ConcurrentSkipListMap.class);
|
||||
|
||||
static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
|
||||
String field, Class<?> klazz) {
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long headOffset;
|
||||
static {
|
||||
try {
|
||||
return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
|
||||
} catch (NoSuchFieldException e) {
|
||||
// Convert Exception to corresponding Error
|
||||
NoSuchFieldError error = new NoSuchFieldError(field);
|
||||
error.initCause(e);
|
||||
throw error;
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class k = ConcurrentSkipListMap.class;
|
||||
headOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("head"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -470,16 +470,20 @@ public class ConcurrentSkipListSet<E>
|
||||
}
|
||||
|
||||
// Support for resetting map in clone
|
||||
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
||||
private void setMap(ConcurrentNavigableMap<E,Object> map) {
|
||||
UNSAFE.putObjectVolatile(this, mapOffset, map);
|
||||
}
|
||||
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long mapOffset;
|
||||
static {
|
||||
try {
|
||||
mapOffset = unsafe.objectFieldOffset
|
||||
(ConcurrentSkipListSet.class.getDeclaredField("m"));
|
||||
} catch (Exception ex) { throw new Error(ex); }
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class k = ConcurrentSkipListSet.class;
|
||||
mapOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("m"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
private void setMap(ConcurrentNavigableMap<E,Object> map) {
|
||||
unsafe.putObjectVolatile(this, mapOffset, map);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1318,16 +1318,19 @@ public class CopyOnWriteArrayList<E>
|
||||
}
|
||||
|
||||
// Support for resetting lock while deserializing
|
||||
private static final Unsafe unsafe = Unsafe.getUnsafe();
|
||||
private void resetLock() {
|
||||
UNSAFE.putObjectVolatile(this, lockOffset, new ReentrantLock());
|
||||
}
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long lockOffset;
|
||||
static {
|
||||
try {
|
||||
lockOffset = unsafe.objectFieldOffset
|
||||
(CopyOnWriteArrayList.class.getDeclaredField("lock"));
|
||||
} catch (Exception ex) { throw new Error(ex); }
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class k = CopyOnWriteArrayList.class;
|
||||
lockOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("lock"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
private void resetLock() {
|
||||
unsafe.putObjectVolatile(this, lockOffset, new ReentrantLock());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -525,16 +525,27 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unsafe mechanics
|
||||
private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
private static final long nextOffset =
|
||||
objectFieldOffset(UNSAFE, "next", Node.class);
|
||||
private static final long itemOffset =
|
||||
objectFieldOffset(UNSAFE, "item", Node.class);
|
||||
private static final long waiterOffset =
|
||||
objectFieldOffset(UNSAFE, "waiter", Node.class);
|
||||
|
||||
private static final long serialVersionUID = -3375979862319811754L;
|
||||
|
||||
// Unsafe mechanics
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long itemOffset;
|
||||
private static final long nextOffset;
|
||||
private static final long waiterOffset;
|
||||
static {
|
||||
try {
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class k = Node.class;
|
||||
itemOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("item"));
|
||||
nextOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("next"));
|
||||
waiterOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("waiter"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** head of the queue; null until first enqueue */
|
||||
@ -1312,23 +1323,22 @@ public class LinkedTransferQueue<E> extends AbstractQueue<E>
|
||||
|
||||
// Unsafe mechanics
|
||||
|
||||
private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
private static final long headOffset =
|
||||
objectFieldOffset(UNSAFE, "head", LinkedTransferQueue.class);
|
||||
private static final long tailOffset =
|
||||
objectFieldOffset(UNSAFE, "tail", LinkedTransferQueue.class);
|
||||
private static final long sweepVotesOffset =
|
||||
objectFieldOffset(UNSAFE, "sweepVotes", LinkedTransferQueue.class);
|
||||
|
||||
static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
|
||||
String field, Class<?> klazz) {
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long headOffset;
|
||||
private static final long tailOffset;
|
||||
private static final long sweepVotesOffset;
|
||||
static {
|
||||
try {
|
||||
return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
|
||||
} catch (NoSuchFieldException e) {
|
||||
// Convert Exception to corresponding Error
|
||||
NoSuchFieldError error = new NoSuchFieldError(field);
|
||||
error.initCause(e);
|
||||
throw error;
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class k = LinkedTransferQueue.class;
|
||||
headOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("head"));
|
||||
tailOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("tail"));
|
||||
sweepVotesOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("sweepVotes"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1137,18 +1137,16 @@ public class Phaser {
|
||||
|
||||
// Unsafe mechanics
|
||||
|
||||
private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
private static final long stateOffset =
|
||||
objectFieldOffset("state", Phaser.class);
|
||||
|
||||
private static long objectFieldOffset(String field, Class<?> klazz) {
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long stateOffset;
|
||||
static {
|
||||
try {
|
||||
return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
|
||||
} catch (NoSuchFieldException e) {
|
||||
// Convert Exception to corresponding Error
|
||||
NoSuchFieldError error = new NoSuchFieldError(field);
|
||||
error.initCause(e);
|
||||
throw error;
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class k = Phaser.class;
|
||||
stateOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("state"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -963,21 +963,16 @@ public class PriorityBlockingQueue<E> extends AbstractQueue<E>
|
||||
}
|
||||
|
||||
// Unsafe mechanics
|
||||
private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
private static final long allocationSpinLockOffset =
|
||||
objectFieldOffset(UNSAFE, "allocationSpinLock",
|
||||
PriorityBlockingQueue.class);
|
||||
|
||||
static long objectFieldOffset(sun.misc.Unsafe UNSAFE,
|
||||
String field, Class<?> klazz) {
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long allocationSpinLockOffset;
|
||||
static {
|
||||
try {
|
||||
return UNSAFE.objectFieldOffset(klazz.getDeclaredField(field));
|
||||
} catch (NoSuchFieldException e) {
|
||||
// Convert Exception to corresponding Error
|
||||
NoSuchFieldError error = new NoSuchFieldError(field);
|
||||
error.initCause(e);
|
||||
throw error;
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class k = PriorityBlockingQueue.class;
|
||||
allocationSpinLockOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("allocationSpinLock"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -279,12 +279,22 @@ public class SynchronousQueue<E> extends AbstractQueue<E>
|
||||
}
|
||||
|
||||
// Unsafe mechanics
|
||||
private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
private static final long nextOffset =
|
||||
objectFieldOffset(UNSAFE, "next", SNode.class);
|
||||
private static final long matchOffset =
|
||||
objectFieldOffset(UNSAFE, "match", SNode.class);
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long matchOffset;
|
||||
private static final long nextOffset;
|
||||
|
||||
static {
|
||||
try {
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class k = SNode.class;
|
||||
matchOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("match"));
|
||||
nextOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("next"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** The head (top) of the stack */
|
||||
@ -498,10 +508,18 @@ public class SynchronousQueue<E> extends AbstractQueue<E>
|
||||
}
|
||||
|
||||
// Unsafe mechanics
|
||||
private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
private static final long headOffset =
|
||||
objectFieldOffset(UNSAFE, "head", TransferStack.class);
|
||||
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long headOffset;
|
||||
static {
|
||||
try {
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class k = TransferStack.class;
|
||||
headOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("head"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Dual Queue */
|
||||
@ -558,11 +576,22 @@ public class SynchronousQueue<E> extends AbstractQueue<E>
|
||||
}
|
||||
|
||||
// Unsafe mechanics
|
||||
private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
private static final long nextOffset =
|
||||
objectFieldOffset(UNSAFE, "next", QNode.class);
|
||||
private static final long itemOffset =
|
||||
objectFieldOffset(UNSAFE, "item", QNode.class);
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long itemOffset;
|
||||
private static final long nextOffset;
|
||||
|
||||
static {
|
||||
try {
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class k = QNode.class;
|
||||
itemOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("item"));
|
||||
nextOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("next"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Head of queue */
|
||||
@ -791,15 +820,24 @@ public class SynchronousQueue<E> extends AbstractQueue<E>
|
||||
}
|
||||
}
|
||||
|
||||
// unsafe mechanics
|
||||
private static final sun.misc.Unsafe UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
private static final long headOffset =
|
||||
objectFieldOffset(UNSAFE, "head", TransferQueue.class);
|
||||
private static final long tailOffset =
|
||||
objectFieldOffset(UNSAFE, "tail", TransferQueue.class);
|
||||
private static final long cleanMeOffset =
|
||||
objectFieldOffset(UNSAFE, "cleanMe", TransferQueue.class);
|
||||
|
||||
private static final sun.misc.Unsafe UNSAFE;
|
||||
private static final long headOffset;
|
||||
private static final long tailOffset;
|
||||
private static final long cleanMeOffset;
|
||||
static {
|
||||
try {
|
||||
UNSAFE = sun.misc.Unsafe.getUnsafe();
|
||||
Class k = TransferQueue.class;
|
||||
headOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("head"));
|
||||
tailOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("tail"));
|
||||
cleanMeOffset = UNSAFE.objectFieldOffset
|
||||
(k.getDeclaredField("cleanMe"));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user