ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ConcurrentHashMap.java
(Generate patch)

Comparing jsr166/src/main/java/util/concurrent/ConcurrentHashMap.java (file contents):
Revision 1.257 by jsr166, Tue Jun 3 23:49:57 2014 UTC vs.
Revision 1.287 by jsr166, Sun Oct 25 03:34:04 2015 UTC

# Line 13 | Line 13 | import java.lang.reflect.Type;
13   import java.util.AbstractMap;
14   import java.util.Arrays;
15   import java.util.Collection;
16 import java.util.Comparator;
16   import java.util.Enumeration;
17   import java.util.HashMap;
18   import java.util.Hashtable;
# Line 22 | Line 21 | import java.util.Map;
21   import java.util.NoSuchElementException;
22   import java.util.Set;
23   import java.util.Spliterator;
25 import java.util.concurrent.ConcurrentMap;
26 import java.util.concurrent.ForkJoinPool;
24   import java.util.concurrent.atomic.AtomicReference;
25   import java.util.concurrent.locks.LockSupport;
26   import java.util.concurrent.locks.ReentrantLock;
27   import java.util.function.BiConsumer;
28   import java.util.function.BiFunction;
32 import java.util.function.BinaryOperator;
29   import java.util.function.Consumer;
30   import java.util.function.DoubleBinaryOperator;
31   import java.util.function.Function;
32   import java.util.function.IntBinaryOperator;
33   import java.util.function.LongBinaryOperator;
34 + import java.util.function.Predicate;
35   import java.util.function.ToDoubleBiFunction;
36   import java.util.function.ToDoubleFunction;
37   import java.util.function.ToIntBiFunction;
# Line 124 | Line 121 | import java.util.stream.Stream;
121   * being concurrently updated by other threads; for example, when
122   * computing a snapshot summary of the values in a shared registry.
123   * There are three kinds of operation, each with four forms, accepting
124 < * functions with Keys, Values, Entries, and (Key, Value) arguments
125 < * and/or return values. Because the elements of a ConcurrentHashMap
126 < * are not ordered in any particular way, and may be processed in
127 < * different orders in different parallel executions, the correctness
128 < * of supplied functions should not depend on any ordering, or on any
129 < * other objects or values that may transiently change while
130 < * computation is in progress; and except for forEach actions, should
131 < * ideally be side-effect-free. Bulk operations on {@link java.util.Map.Entry}
132 < * objects do not support method {@code setValue}.
124 > * functions with keys, values, entries, and (key, value) pairs as
125 > * arguments and/or return values. Because the elements of a
126 > * ConcurrentHashMap are not ordered in any particular way, and may be
127 > * processed in different orders in different parallel executions, the
128 > * correctness of supplied functions should not depend on any
129 > * ordering, or on any other objects or values that may transiently
130 > * change while computation is in progress; and except for forEach
131 > * actions, should ideally be side-effect-free. Bulk operations on
132 > * {@link java.util.Map.Entry} objects do not support method {@code
133 > * setValue}.
134   *
135   * <ul>
136 < * <li> forEach: Perform a given action on each element.
136 > * <li>forEach: Performs a given action on each element.
137   * A variant form applies a given transformation on each element
138 < * before performing the action.</li>
138 > * before performing the action.
139   *
140 < * <li> search: Return the first available non-null result of
140 > * <li>search: Returns the first available non-null result of
141   * applying a given function on each element; skipping further
142 < * search when a result is found.</li>
142 > * search when a result is found.
143   *
144 < * <li> reduce: Accumulate each element.  The supplied reduction
144 > * <li>reduce: Accumulates each element.  The supplied reduction
145   * function cannot rely on ordering (more formally, it should be
146   * both associative and commutative).  There are five variants:
147   *
148   * <ul>
149   *
150 < * <li> Plain reductions. (There is not a form of this method for
150 > * <li>Plain reductions. (There is not a form of this method for
151   * (key, value) function arguments since there is no corresponding
152 < * return type.)</li>
152 > * return type.)
153   *
154 < * <li> Mapped reductions that accumulate the results of a given
155 < * function applied to each element.</li>
154 > * <li>Mapped reductions that accumulate the results of a given
155 > * function applied to each element.
156   *
157 < * <li> Reductions to scalar doubles, longs, and ints, using a
158 < * given basis value.</li>
157 > * <li>Reductions to scalar doubles, longs, and ints, using a
158 > * given basis value.
159   *
160   * </ul>
163 * </li>
161   * </ul>
162   *
163   * <p>These bulk operations accept a {@code parallelismThreshold}
# Line 451 | Line 448 | public class ConcurrentHashMap<K,V> exte
448       *
449       * Maintaining API and serialization compatibility with previous
450       * versions of this class introduces several oddities. Mainly: We
451 <     * leave untouched but unused constructor arguments refering to
451 >     * leave untouched but unused constructor arguments referring to
452       * concurrencyLevel. We accept a loadFactor constructor argument,
453       * but apply it only to initial table capacity (which is the only
454       * time that we can guarantee to honor it.) We also declare an
# Line 546 | Line 543 | public class ConcurrentHashMap<K,V> exte
543       * The number of bits used for generation stamp in sizeCtl.
544       * Must be at least 6 for 32bit arrays.
545       */
546 <    private static int RESIZE_STAMP_BITS = 16;
546 >    private static final int RESIZE_STAMP_BITS = 16;
547  
548      /**
549       * The maximum number of threads that can help resize.
# Line 570 | Line 567 | public class ConcurrentHashMap<K,V> exte
567      /** Number of CPUS, to place bounds on some sizings */
568      static final int NCPU = Runtime.getRuntime().availableProcessors();
569  
570 <    /** For serialization compatibility. */
570 >    /**
571 >     * Serialized pseudo-fields, provided only for jdk7 compatibility.
572 >     * @serialField segments Segment[]
573 >     *   The segments, each of which is a specialized hash table.
574 >     * @serialField segmentMask int
575 >     *   Mask value for indexing into segments. The upper bits of a
576 >     *   key's hash code are used to choose the segment.
577 >     * @serialField segmentShift int
578 >     *   Shift value for indexing within segments.
579 >     */
580      private static final ObjectStreamField[] serialPersistentFields = {
581          new ObjectStreamField("segments", Segment[].class),
582          new ObjectStreamField("segmentMask", Integer.TYPE),
583 <        new ObjectStreamField("segmentShift", Integer.TYPE)
583 >        new ObjectStreamField("segmentShift", Integer.TYPE),
584      };
585  
586      /* ---------------- Nodes -------------- */
# Line 600 | Line 606 | public class ConcurrentHashMap<K,V> exte
606              this.next = next;
607          }
608  
609 <        public final K getKey()       { return key; }
610 <        public final V getValue()     { return val; }
611 <        public final int hashCode()   { return key.hashCode() ^ val.hashCode(); }
612 <        public final String toString(){ return key + "=" + val; }
609 >        public final K getKey()     { return key; }
610 >        public final V getValue()   { return val; }
611 >        public final int hashCode() { return key.hashCode() ^ val.hashCode(); }
612 >        public final String toString() {
613 >            return Helpers.mapEntryToString(key, val);
614 >        }
615          public final V setValue(V value) {
616              throw new UnsupportedOperationException();
617          }
# Line 1027 | Line 1035 | public class ConcurrentHashMap<K,V> exte
1035                                      p.val = value;
1036                              }
1037                          }
1038 +                        else if (f instanceof ReservationNode)
1039 +                            throw new IllegalStateException("Recursive update");
1040                      }
1041                  }
1042                  if (binCount != 0) {
# Line 1129 | Line 1139 | public class ConcurrentHashMap<K,V> exte
1139                                  }
1140                              }
1141                          }
1142 +                        else if (f instanceof ReservationNode)
1143 +                            throw new IllegalStateException("Recursive update");
1144                      }
1145                  }
1146                  if (validated) {
# Line 1336 | Line 1348 | public class ConcurrentHashMap<K,V> exte
1348  
1349      /**
1350       * Stripped-down version of helper class used in previous version,
1351 <     * declared for the sake of serialization compatibility
1351 >     * declared for the sake of serialization compatibility.
1352       */
1353      static class Segment<K,V> extends ReentrantLock implements Serializable {
1354          private static final long serialVersionUID = 2249069246763182397L;
# Line 1350 | Line 1362 | public class ConcurrentHashMap<K,V> exte
1362       * @param s the stream
1363       * @throws java.io.IOException if an I/O error occurs
1364       * @serialData
1365 <     * the key (Object) and value (Object)
1366 <     * for each key-value mapping, followed by a null pair.
1365 >     * the serialized fields, followed by the key (Object) and value
1366 >     * (Object) for each key-value mapping, followed by a null pair.
1367       * The key-value mappings are emitted in no particular order.
1368       */
1369      private void writeObject(java.io.ObjectOutputStream s)
# Line 1371 | Line 1383 | public class ConcurrentHashMap<K,V> exte
1383              new Segment<?,?>[DEFAULT_CONCURRENCY_LEVEL];
1384          for (int i = 0; i < segments.length; ++i)
1385              segments[i] = new Segment<K,V>(LOAD_FACTOR);
1386 <        s.putFields().put("segments", segments);
1387 <        s.putFields().put("segmentShift", segmentShift);
1388 <        s.putFields().put("segmentMask", segmentMask);
1386 >        java.io.ObjectOutputStream.PutField streamFields = s.putFields();
1387 >        streamFields.put("segments", segments);
1388 >        streamFields.put("segmentShift", segmentShift);
1389 >        streamFields.put("segmentMask", segmentMask);
1390          s.writeFields();
1391  
1392          Node<K,V>[] t;
# Line 1386 | Line 1399 | public class ConcurrentHashMap<K,V> exte
1399          }
1400          s.writeObject(null);
1401          s.writeObject(null);
1389        segments = null; // throw away
1402      }
1403  
1404      /**
# Line 1590 | Line 1602 | public class ConcurrentHashMap<K,V> exte
1602      }
1603  
1604      /**
1605 +     * Helper method for EntrySetView.removeIf.
1606 +     */
1607 +    boolean removeEntryIf(Predicate<? super Entry<K,V>> function) {
1608 +        if (function == null) throw new NullPointerException();
1609 +        Node<K,V>[] t;
1610 +        boolean removed = false;
1611 +        if ((t = table) != null) {
1612 +            Traverser<K,V> it = new Traverser<K,V>(t, t.length, 0, t.length);
1613 +            for (Node<K,V> p; (p = it.advance()) != null; ) {
1614 +                K k = p.key;
1615 +                V v = p.val;
1616 +                Map.Entry<K,V> e = new AbstractMap.SimpleImmutableEntry<>(k, v);
1617 +                if (function.test(e) && replaceNode(k, null, v) != null)
1618 +                    removed = true;
1619 +            }
1620 +        }
1621 +        return removed;
1622 +    }
1623 +
1624 +    /**
1625 +     * Helper method for ValuesView.removeIf.
1626 +     */
1627 +    boolean removeValueIf(Predicate<? super V> function) {
1628 +        if (function == null) throw new NullPointerException();
1629 +        Node<K,V>[] t;
1630 +        boolean removed = false;
1631 +        if ((t = table) != null) {
1632 +            Traverser<K,V> it = new Traverser<K,V>(t, t.length, 0, t.length);
1633 +            for (Node<K,V> p; (p = it.advance()) != null; ) {
1634 +                K k = p.key;
1635 +                V v = p.val;
1636 +                if (function.test(v) && replaceNode(k, null, v) != null)
1637 +                    removed = true;
1638 +            }
1639 +        }
1640 +        return removed;
1641 +    }
1642 +
1643 +    /**
1644       * If the specified key is not already associated with a value,
1645       * attempts to compute its value using the given mapping function
1646       * and enters it into this map unless {@code null}.  The entire
# Line 1647 | Line 1698 | public class ConcurrentHashMap<K,V> exte
1698                          if (fh >= 0) {
1699                              binCount = 1;
1700                              for (Node<K,V> e = f;; ++binCount) {
1701 <                                K ek; V ev;
1701 >                                K ek;
1702                                  if (e.hash == h &&
1703                                      ((ek = e.key) == key ||
1704                                       (ek != null && key.equals(ek)))) {
# Line 1657 | Line 1708 | public class ConcurrentHashMap<K,V> exte
1708                                  Node<K,V> pred = e;
1709                                  if ((e = e.next) == null) {
1710                                      if ((val = mappingFunction.apply(key)) != null) {
1711 +                                        if (pred.next != null)
1712 +                                            throw new IllegalStateException("Recursive update");
1713                                          added = true;
1714                                          pred.next = new Node<K,V>(h, key, val, null);
1715                                      }
# Line 1676 | Line 1729 | public class ConcurrentHashMap<K,V> exte
1729                                  t.putTreeVal(h, key, val);
1730                              }
1731                          }
1732 +                        else if (f instanceof ReservationNode)
1733 +                            throw new IllegalStateException("Recursive update");
1734                      }
1735                  }
1736                  if (binCount != 0) {
# Line 1771 | Line 1826 | public class ConcurrentHashMap<K,V> exte
1826                                  }
1827                              }
1828                          }
1829 +                        else if (f instanceof ReservationNode)
1830 +                            throw new IllegalStateException("Recursive update");
1831                      }
1832                  }
1833                  if (binCount != 0)
# Line 1862 | Line 1919 | public class ConcurrentHashMap<K,V> exte
1919                                  if ((e = e.next) == null) {
1920                                      val = remappingFunction.apply(key, null);
1921                                      if (val != null) {
1922 +                                        if (pred.next != null)
1923 +                                            throw new IllegalStateException("Recursive update");
1924                                          delta = 1;
1925                                          pred.next =
1926                                              new Node<K,V>(h, key, val, null);
# Line 1894 | Line 1953 | public class ConcurrentHashMap<K,V> exte
1953                                      setTabAt(tab, i, untreeify(t.first));
1954                              }
1955                          }
1956 +                        else if (f instanceof ReservationNode)
1957 +                            throw new IllegalStateException("Recursive update");
1958                      }
1959                  }
1960                  if (binCount != 0) {
# Line 2003 | Line 2064 | public class ConcurrentHashMap<K,V> exte
2064                                      setTabAt(tab, i, untreeify(t.first));
2065                              }
2066                          }
2067 +                        else if (f instanceof ReservationNode)
2068 +                            throw new IllegalStateException("Recursive update");
2069                      }
2070                  }
2071                  if (binCount != 0) {
# Line 2020 | Line 2083 | public class ConcurrentHashMap<K,V> exte
2083      // Hashtable legacy methods
2084  
2085      /**
2086 <     * Legacy method testing if some key maps into the specified value
2024 <     * in this table.
2086 >     * Tests if some key maps into the specified value in this table.
2087       *
2088 <     * @deprecated This method is identical in functionality to
2088 >     * <p>Note that this method is identical in functionality to
2089       * {@link #containsValue(Object)}, and exists solely to ensure
2090       * full compatibility with class {@link java.util.Hashtable},
2091       * which supported this method prior to introduction of the
2092 <     * Java Collections framework.
2092 >     * Java Collections Framework.
2093       *
2094       * @param  value a value to search for
2095       * @return {@code true} if and only if some key maps to the
# Line 2036 | Line 2098 | public class ConcurrentHashMap<K,V> exte
2098       *         {@code false} otherwise
2099       * @throws NullPointerException if the specified value is null
2100       */
2039    @Deprecated
2101      public boolean contains(Object value) {
2102          return containsValue(value);
2103      }
# Line 2169 | Line 2230 | public class ConcurrentHashMap<K,V> exte
2230      }
2231  
2232      /**
2233 <     * A place-holder node used in computeIfAbsent and compute
2233 >     * A place-holder node used in computeIfAbsent and compute.
2234       */
2235      static final class ReservationNode<K,V> extends Node<K,V> {
2236          ReservationNode() {
# Line 2318 | Line 2379 | public class ConcurrentHashMap<K,V> exte
2379                  break;
2380              else if (tab == table) {
2381                  int rs = resizeStamp(n);
2382 <                if (sc < 0) {
2383 <                    Node<K,V>[] nt;
2323 <                    if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
2324 <                        sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
2325 <                        transferIndex <= 0)
2326 <                        break;
2327 <                    if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))
2328 <                        transfer(tab, nt);
2329 <                }
2330 <                else if (U.compareAndSwapInt(this, SIZECTL, sc,
2331 <                                             (rs << RESIZE_STAMP_SHIFT) + 2))
2382 >                if (U.compareAndSwapInt(this, SIZECTL, sc,
2383 >                                        (rs << RESIZE_STAMP_SHIFT) + 2))
2384                      transfer(tab, null);
2385              }
2386          }
# Line 2583 | Line 2635 | public class ConcurrentHashMap<K,V> exte
2635       * too small, in which case resizes instead.
2636       */
2637      private final void treeifyBin(Node<K,V>[] tab, int index) {
2638 <        Node<K,V> b; int n, sc;
2638 >        Node<K,V> b; int n;
2639          if (tab != null) {
2640              if ((n = tab.length) < MIN_TREEIFY_CAPACITY)
2641                  tryPresize(n << 1);
# Line 2627 | Line 2679 | public class ConcurrentHashMap<K,V> exte
2679      /* ---------------- TreeNodes -------------- */
2680  
2681      /**
2682 <     * Nodes for use in TreeBins
2682 >     * Nodes for use in TreeBins.
2683       */
2684      static final class TreeNode<K,V> extends Node<K,V> {
2685          TreeNode<K,V> parent;  // red-black tree links
# Line 2746 | Line 2798 | public class ConcurrentHashMap<K,V> exte
2798                                    (kc = comparableClassFor(k)) == null) ||
2799                                   (dir = compareComparables(kc, k, pk)) == 0)
2800                              dir = tieBreakOrder(k, pk);
2801 <                            TreeNode<K,V> xp = p;
2801 >                        TreeNode<K,V> xp = p;
2802                          if ((p = (dir <= 0) ? p.left : p.right) == null) {
2803                              x.parent = xp;
2804                              if (dir <= 0)
# Line 3190 | Line 3242 | public class ConcurrentHashMap<K,V> exte
3242          }
3243  
3244          /**
3245 <         * Recursive invariant check
3245 >         * Checks invariants recursively for the tree of Nodes rooted at t.
3246           */
3247          static <K,V> boolean checkInvariants(TreeNode<K,V> t) {
3248              TreeNode<K,V> tp = t.parent, tl = t.left, tr = t.right,
# Line 3214 | Line 3266 | public class ConcurrentHashMap<K,V> exte
3266              return true;
3267          }
3268  
3269 <        private static final sun.misc.Unsafe U;
3269 >        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
3270          private static final long LOCKSTATE;
3271          static {
3272              try {
3221                U = sun.misc.Unsafe.getUnsafe();
3222                Class<?> k = TreeBin.class;
3273                  LOCKSTATE = U.objectFieldOffset
3274 <                    (k.getDeclaredField("lockState"));
3275 <            } catch (Exception e) {
3274 >                    (TreeBin.class.getDeclaredField("lockState"));
3275 >            } catch (ReflectiveOperationException e) {
3276                  throw new Error(e);
3277              }
3278          }
# Line 3437 | Line 3487 | public class ConcurrentHashMap<K,V> exte
3487      }
3488  
3489      /**
3490 <     * Exported Entry for EntryIterator
3490 >     * Exported Entry for EntryIterator.
3491       */
3492      static final class MapEntry<K,V> implements Map.Entry<K,V> {
3493          final K key; // non-null
# Line 3451 | Line 3501 | public class ConcurrentHashMap<K,V> exte
3501          public K getKey()        { return key; }
3502          public V getValue()      { return val; }
3503          public int hashCode()    { return key.hashCode() ^ val.hashCode(); }
3504 <        public String toString() { return key + "=" + val; }
3504 >        public String toString() {
3505 >            return Helpers.mapEntryToString(key, val);
3506 >        }
3507  
3508          public boolean equals(Object o) {
3509              Object k, v; Map.Entry<?,?> e;
# Line 3488 | Line 3540 | public class ConcurrentHashMap<K,V> exte
3540              this.est = est;
3541          }
3542  
3543 <        public Spliterator<K> trySplit() {
3543 >        public KeySpliterator<K,V> trySplit() {
3544              int i, f, h;
3545              return (h = ((i = baseIndex) + (f = baseLimit)) >>> 1) <= i ? null :
3546                  new KeySpliterator<K,V>(tab, baseSize, baseLimit = h,
# Line 3527 | Line 3579 | public class ConcurrentHashMap<K,V> exte
3579              this.est = est;
3580          }
3581  
3582 <        public Spliterator<V> trySplit() {
3582 >        public ValueSpliterator<K,V> trySplit() {
3583              int i, f, h;
3584              return (h = ((i = baseIndex) + (f = baseLimit)) >>> 1) <= i ? null :
3585                  new ValueSpliterator<K,V>(tab, baseSize, baseLimit = h,
# Line 3567 | Line 3619 | public class ConcurrentHashMap<K,V> exte
3619              this.est = est;
3620          }
3621  
3622 <        public Spliterator<Map.Entry<K,V>> trySplit() {
3622 >        public EntrySpliterator<K,V> trySplit() {
3623              int i, f, h;
3624              return (h = ((i = baseIndex) + (f = baseLimit)) >>> 1) <= i ? null :
3625                  new EntrySpliterator<K,V>(tab, baseSize, baseLimit = h,
# Line 4379 | Line 4431 | public class ConcurrentHashMap<K,V> exte
4431          public abstract boolean contains(Object o);
4432          public abstract boolean remove(Object o);
4433  
4434 <        private static final String oomeMsg = "Required array size too large";
4434 >        private static final String OOME_MSG = "Required array size too large";
4435  
4436          public final Object[] toArray() {
4437              long sz = map.mappingCount();
4438              if (sz > MAX_ARRAY_SIZE)
4439 <                throw new OutOfMemoryError(oomeMsg);
4439 >                throw new OutOfMemoryError(OOME_MSG);
4440              int n = (int)sz;
4441              Object[] r = new Object[n];
4442              int i = 0;
4443              for (E e : this) {
4444                  if (i == n) {
4445                      if (n >= MAX_ARRAY_SIZE)
4446 <                        throw new OutOfMemoryError(oomeMsg);
4446 >                        throw new OutOfMemoryError(OOME_MSG);
4447                      if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
4448                          n = MAX_ARRAY_SIZE;
4449                      else
# Line 4407 | Line 4459 | public class ConcurrentHashMap<K,V> exte
4459          public final <T> T[] toArray(T[] a) {
4460              long sz = map.mappingCount();
4461              if (sz > MAX_ARRAY_SIZE)
4462 <                throw new OutOfMemoryError(oomeMsg);
4462 >                throw new OutOfMemoryError(OOME_MSG);
4463              int m = (int)sz;
4464              T[] r = (a.length >= m) ? a :
4465                  (T[])java.lang.reflect.Array
# Line 4417 | Line 4469 | public class ConcurrentHashMap<K,V> exte
4469              for (E e : this) {
4470                  if (i == n) {
4471                      if (n >= MAX_ARRAY_SIZE)
4472 <                        throw new OutOfMemoryError(oomeMsg);
4472 >                        throw new OutOfMemoryError(OOME_MSG);
4473                      if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
4474                          n = MAX_ARRAY_SIZE;
4475                      else
# Line 4664 | Line 4716 | public class ConcurrentHashMap<K,V> exte
4716              throw new UnsupportedOperationException();
4717          }
4718  
4719 +        public boolean removeIf(Predicate<? super V> filter) {
4720 +            return map.removeValueIf(filter);
4721 +        }
4722 +
4723          public Spliterator<V> spliterator() {
4724              Node<K,V>[] t;
4725              ConcurrentHashMap<K,V> m = map;
# Line 4733 | Line 4789 | public class ConcurrentHashMap<K,V> exte
4789              return added;
4790          }
4791  
4792 +        public boolean removeIf(Predicate<? super Entry<K,V>> filter) {
4793 +            return map.removeEntryIf(filter);
4794 +        }
4795 +
4796          public final int hashCode() {
4797              int h = 0;
4798              Node<K,V>[] t;
# Line 4804 | Line 4864 | public class ConcurrentHashMap<K,V> exte
4864          }
4865  
4866          /**
4867 <         * Same as Traverser version
4867 >         * Same as Traverser version.
4868           */
4869          final Node<K,V> advance() {
4870              Node<K,V> e;
# Line 6249 | Line 6309 | public class ConcurrentHashMap<K,V> exte
6309      }
6310  
6311      // Unsafe mechanics
6312 <    private static final sun.misc.Unsafe U;
6312 >    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
6313      private static final long SIZECTL;
6314      private static final long TRANSFERINDEX;
6315      private static final long BASECOUNT;
6316      private static final long CELLSBUSY;
6317      private static final long CELLVALUE;
6318 <    private static final long ABASE;
6318 >    private static final int ABASE;
6319      private static final int ASHIFT;
6320  
6321      static {
6322          try {
6263            U = sun.misc.Unsafe.getUnsafe();
6264            Class<?> k = ConcurrentHashMap.class;
6323              SIZECTL = U.objectFieldOffset
6324 <                (k.getDeclaredField("sizeCtl"));
6324 >                (ConcurrentHashMap.class.getDeclaredField("sizeCtl"));
6325              TRANSFERINDEX = U.objectFieldOffset
6326 <                (k.getDeclaredField("transferIndex"));
6326 >                (ConcurrentHashMap.class.getDeclaredField("transferIndex"));
6327              BASECOUNT = U.objectFieldOffset
6328 <                (k.getDeclaredField("baseCount"));
6328 >                (ConcurrentHashMap.class.getDeclaredField("baseCount"));
6329              CELLSBUSY = U.objectFieldOffset
6330 <                (k.getDeclaredField("cellsBusy"));
6331 <            Class<?> ck = CounterCell.class;
6330 >                (ConcurrentHashMap.class.getDeclaredField("cellsBusy"));
6331 >
6332              CELLVALUE = U.objectFieldOffset
6333 <                (ck.getDeclaredField("value"));
6334 <            Class<?> ak = Node[].class;
6335 <            ABASE = U.arrayBaseOffset(ak);
6336 <            int scale = U.arrayIndexScale(ak);
6333 >                (CounterCell.class.getDeclaredField("value"));
6334 >
6335 >            ABASE = U.arrayBaseOffset(Node[].class);
6336 >            int scale = U.arrayIndexScale(Node[].class);
6337              if ((scale & (scale - 1)) != 0)
6338 <                throw new Error("data type scale not a power of two");
6338 >                throw new Error("array index scale not a power of two");
6339              ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
6340 <        } catch (Exception e) {
6340 >        } catch (ReflectiveOperationException e) {
6341              throw new Error(e);
6342          }
6343 +
6344 +        // Reduce the risk of rare disastrous classloading in first call to
6345 +        // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
6346 +        Class<?> ensureLoaded = LockSupport.class;
6347      }
6348   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines