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.252 by dl, Sun Dec 1 13:38:58 2013 UTC vs.
Revision 1.283 by jsr166, Sat Sep 19 20:34:42 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 104 | Line 101 | import java.util.stream.Stream;
101   * mapped values are (perhaps transiently) not used or all take the
102   * same mapping value.
103   *
104 < * <p>A ConcurrentHashMap can be used as scalable frequency map (a
104 > * <p>A ConcurrentHashMap can be used as a scalable frequency map (a
105   * form of histogram or multiset) by using {@link
106   * java.util.concurrent.atomic.LongAdder} values and initializing via
107   * {@link #computeIfAbsent computeIfAbsent}. For example, to add a count
108   * to a {@code ConcurrentHashMap<String,LongAdder> freqs}, you can use
109 < * {@code freqs.computeIfAbsent(k -> new LongAdder()).increment();}
109 > * {@code freqs.computeIfAbsent(key, k -> new LongAdder()).increment();}
110   *
111   * <p>This class and its views and iterators implement all of the
112   * <em>optional</em> methods of the {@link Map} and {@link Iterator}
# 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 574 | Line 571 | public class ConcurrentHashMap<K,V> exte
571      private static final ObjectStreamField[] serialPersistentFields = {
572          new ObjectStreamField("segments", Segment[].class),
573          new ObjectStreamField("segmentMask", Integer.TYPE),
574 <        new ObjectStreamField("segmentShift", Integer.TYPE)
574 >        new ObjectStreamField("segmentShift", Integer.TYPE),
575      };
576  
577      /* ---------------- Nodes -------------- */
# Line 600 | Line 597 | public class ConcurrentHashMap<K,V> exte
597              this.next = next;
598          }
599  
600 <        public final K getKey()       { return key; }
601 <        public final V getValue()     { return val; }
602 <        public final int hashCode()   { return key.hashCode() ^ val.hashCode(); }
603 <        public final String toString(){ return key + "=" + val; }
600 >        public final K getKey()     { return key; }
601 >        public final V getValue()   { return val; }
602 >        public final int hashCode() { return key.hashCode() ^ val.hashCode(); }
603 >        public final String toString() {
604 >            return Helpers.mapEntryToString(key, val);
605 >        }
606          public final V setValue(V value) {
607              throw new UnsupportedOperationException();
608          }
# Line 1027 | Line 1026 | public class ConcurrentHashMap<K,V> exte
1026                                      p.val = value;
1027                              }
1028                          }
1029 +                        else if (f instanceof ReservationNode)
1030 +                            throw new IllegalStateException("Recursive update");
1031                      }
1032                  }
1033                  if (binCount != 0) {
# Line 1129 | Line 1130 | public class ConcurrentHashMap<K,V> exte
1130                                  }
1131                              }
1132                          }
1133 +                        else if (f instanceof ReservationNode)
1134 +                            throw new IllegalStateException("Recursive update");
1135                      }
1136                  }
1137                  if (validated) {
# Line 1371 | Line 1374 | public class ConcurrentHashMap<K,V> exte
1374              new Segment<?,?>[DEFAULT_CONCURRENCY_LEVEL];
1375          for (int i = 0; i < segments.length; ++i)
1376              segments[i] = new Segment<K,V>(LOAD_FACTOR);
1377 <        s.putFields().put("segments", segments);
1378 <        s.putFields().put("segmentShift", segmentShift);
1379 <        s.putFields().put("segmentMask", segmentMask);
1377 >        java.io.ObjectOutputStream.PutField streamFields = s.putFields();
1378 >        streamFields.put("segments", segments);
1379 >        streamFields.put("segmentShift", segmentShift);
1380 >        streamFields.put("segmentMask", segmentMask);
1381          s.writeFields();
1382  
1383          Node<K,V>[] t;
# Line 1590 | Line 1594 | public class ConcurrentHashMap<K,V> exte
1594      }
1595  
1596      /**
1597 +     * Helper method for EntrySetView.removeIf
1598 +     */
1599 +    boolean removeEntryIf(Predicate<? super Entry<K,V>> function) {
1600 +        if (function == null) throw new NullPointerException();
1601 +        Node<K,V>[] t;
1602 +        boolean removed = false;
1603 +        if ((t = table) != null) {
1604 +            Traverser<K,V> it = new Traverser<K,V>(t, t.length, 0, t.length);
1605 +            for (Node<K,V> p; (p = it.advance()) != null; ) {
1606 +                K k = p.key;
1607 +                V v = p.val;
1608 +                Map.Entry<K,V> e = new AbstractMap.SimpleImmutableEntry<>(k, v);
1609 +                if (function.test(e) && replaceNode(k, null, v) != null)
1610 +                    removed = true;
1611 +            }
1612 +        }
1613 +        return removed;
1614 +    }
1615 +
1616 +    /**
1617 +     * Helper method for ValuesView.removeIf
1618 +     */
1619 +    boolean removeValueIf(Predicate<? super V> function) {
1620 +        if (function == null) throw new NullPointerException();
1621 +        Node<K,V>[] t;
1622 +        boolean removed = false;
1623 +        if ((t = table) != null) {
1624 +            Traverser<K,V> it = new Traverser<K,V>(t, t.length, 0, t.length);
1625 +            for (Node<K,V> p; (p = it.advance()) != null; ) {
1626 +                K k = p.key;
1627 +                V v = p.val;
1628 +                if (function.test(v) && replaceNode(k, null, v) != null)
1629 +                    removed = true;
1630 +            }
1631 +        }
1632 +        return removed;
1633 +    }
1634 +
1635 +    /**
1636       * If the specified key is not already associated with a value,
1637       * attempts to compute its value using the given mapping function
1638       * and enters it into this map unless {@code null}.  The entire
# Line 1647 | Line 1690 | public class ConcurrentHashMap<K,V> exte
1690                          if (fh >= 0) {
1691                              binCount = 1;
1692                              for (Node<K,V> e = f;; ++binCount) {
1693 <                                K ek; V ev;
1693 >                                K ek;
1694                                  if (e.hash == h &&
1695                                      ((ek = e.key) == key ||
1696                                       (ek != null && key.equals(ek)))) {
# Line 1657 | Line 1700 | public class ConcurrentHashMap<K,V> exte
1700                                  Node<K,V> pred = e;
1701                                  if ((e = e.next) == null) {
1702                                      if ((val = mappingFunction.apply(key)) != null) {
1703 +                                        if (pred.next != null)
1704 +                                            throw new IllegalStateException("Recursive update");
1705                                          added = true;
1706                                          pred.next = new Node<K,V>(h, key, val, null);
1707                                      }
# Line 1676 | Line 1721 | public class ConcurrentHashMap<K,V> exte
1721                                  t.putTreeVal(h, key, val);
1722                              }
1723                          }
1724 +                        else if (f instanceof ReservationNode)
1725 +                            throw new IllegalStateException("Recursive update");
1726                      }
1727                  }
1728                  if (binCount != 0) {
# Line 1771 | Line 1818 | public class ConcurrentHashMap<K,V> exte
1818                                  }
1819                              }
1820                          }
1821 +                        else if (f instanceof ReservationNode)
1822 +                            throw new IllegalStateException("Recursive update");
1823                      }
1824                  }
1825                  if (binCount != 0)
# Line 1862 | Line 1911 | public class ConcurrentHashMap<K,V> exte
1911                                  if ((e = e.next) == null) {
1912                                      val = remappingFunction.apply(key, null);
1913                                      if (val != null) {
1914 +                                        if (pred.next != null)
1915 +                                            throw new IllegalStateException("Recursive update");
1916                                          delta = 1;
1917                                          pred.next =
1918                                              new Node<K,V>(h, key, val, null);
# Line 1894 | Line 1945 | public class ConcurrentHashMap<K,V> exte
1945                                      setTabAt(tab, i, untreeify(t.first));
1946                              }
1947                          }
1948 +                        else if (f instanceof ReservationNode)
1949 +                            throw new IllegalStateException("Recursive update");
1950                      }
1951                  }
1952                  if (binCount != 0) {
# Line 2003 | Line 2056 | public class ConcurrentHashMap<K,V> exte
2056                                      setTabAt(tab, i, untreeify(t.first));
2057                              }
2058                          }
2059 +                        else if (f instanceof ReservationNode)
2060 +                            throw new IllegalStateException("Recursive update");
2061                      }
2062                  }
2063                  if (binCount != 0) {
# Line 2020 | Line 2075 | public class ConcurrentHashMap<K,V> exte
2075      // Hashtable legacy methods
2076  
2077      /**
2078 <     * Legacy method testing if some key maps into the specified value
2024 <     * in this table.
2078 >     * Tests if some key maps into the specified value in this table.
2079       *
2080 <     * @deprecated This method is identical in functionality to
2080 >     * <p>Note that this method is identical in functionality to
2081       * {@link #containsValue(Object)}, and exists solely to ensure
2082       * full compatibility with class {@link java.util.Hashtable},
2083       * which supported this method prior to introduction of the
2084 <     * Java Collections framework.
2084 >     * Java Collections Framework.
2085       *
2086       * @param  value a value to search for
2087       * @return {@code true} if and only if some key maps to the
# Line 2036 | Line 2090 | public class ConcurrentHashMap<K,V> exte
2090       *         {@code false} otherwise
2091       * @throws NullPointerException if the specified value is null
2092       */
2039    @Deprecated
2093      public boolean contains(Object value) {
2094          return containsValue(value);
2095      }
# Line 2188 | Line 2241 | public class ConcurrentHashMap<K,V> exte
2241       * Must be negative when shifted left by RESIZE_STAMP_SHIFT.
2242       */
2243      static final int resizeStamp(int n) {
2244 <        return Integer.numberOfLeadingZeros(n) | (1 << (RESIZE_STAMP_BITS - 1));
2244 >        return Integer.numberOfLeadingZeros(n) | (1 << (RESIZE_STAMP_BITS - 1));
2245      }
2246  
2247      /**
# Line 2251 | Line 2304 | public class ConcurrentHashMap<K,V> exte
2304                  int rs = resizeStamp(n);
2305                  if (sc < 0) {
2306                      if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
2307 <                        sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
2308 <                        transferIndex <= 0)
2307 >                        sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
2308 >                        transferIndex <= 0)
2309                          break;
2310                      if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))
2311                          transfer(tab, nt);
2312                  }
2313                  else if (U.compareAndSwapInt(this, SIZECTL, sc,
2314 <                                             (rs << RESIZE_STAMP_SHIFT) + 2))
2314 >                                             (rs << RESIZE_STAMP_SHIFT) + 2))
2315                      transfer(tab, null);
2316                  s = sumCount();
2317              }
# Line 2272 | Line 2325 | public class ConcurrentHashMap<K,V> exte
2325          Node<K,V>[] nextTab; int sc;
2326          if (tab != null && (f instanceof ForwardingNode) &&
2327              (nextTab = ((ForwardingNode<K,V>)f).nextTable) != null) {
2328 <            int rs = resizeStamp(tab.length);
2328 >            int rs = resizeStamp(tab.length);
2329              while (nextTab == nextTable && table == tab &&
2330 <                   (sc = sizeCtl) < 0) {
2331 <                if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
2330 >                   (sc = sizeCtl) < 0) {
2331 >                if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
2332                      sc == rs + MAX_RESIZERS || transferIndex <= 0)
2333 <                    break;
2334 <                if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1)) {
2333 >                    break;
2334 >                if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1)) {
2335                      transfer(tab, nextTab);
2336                      break;
2337                  }
# Line 2318 | Line 2371 | public class ConcurrentHashMap<K,V> exte
2371                  break;
2372              else if (tab == table) {
2373                  int rs = resizeStamp(n);
2374 <                if (sc < 0) {
2375 <                    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))
2374 >                if (U.compareAndSwapInt(this, SIZECTL, sc,
2375 >                                        (rs << RESIZE_STAMP_SHIFT) + 2))
2376                      transfer(tab, null);
2377              }
2378          }
# Line 2386 | Line 2430 | public class ConcurrentHashMap<K,V> exte
2430                      return;
2431                  }
2432                  if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)) {
2433 <                    if ((sc - 2) != resizeStamp(n))
2433 >                    if ((sc - 2) != resizeStamp(n) << RESIZE_STAMP_SHIFT)
2434                          return;
2435                      finishing = advance = true;
2436                      i = n; // recheck before commit
# Line 2583 | Line 2627 | public class ConcurrentHashMap<K,V> exte
2627       * too small, in which case resizes instead.
2628       */
2629      private final void treeifyBin(Node<K,V>[] tab, int index) {
2630 <        Node<K,V> b; int n, sc;
2630 >        Node<K,V> b; int n;
2631          if (tab != null) {
2632              if ((n = tab.length) < MIN_TREEIFY_CAPACITY)
2633                  tryPresize(n << 1);
# Line 2653 | Line 2697 | public class ConcurrentHashMap<K,V> exte
2697          final TreeNode<K,V> findTreeNode(int h, Object k, Class<?> kc) {
2698              if (k != null) {
2699                  TreeNode<K,V> p = this;
2700 <                do  {
2700 >                do {
2701                      int ph, dir; K pk; TreeNode<K,V> q;
2702                      TreeNode<K,V> pl = p.left, pr = p.right;
2703                      if ((ph = p.hash) > h)
# Line 2746 | Line 2790 | public class ConcurrentHashMap<K,V> exte
2790                                    (kc = comparableClassFor(k)) == null) ||
2791                                   (dir = compareComparables(kc, k, pk)) == 0)
2792                              dir = tieBreakOrder(k, pk);
2793 <                            TreeNode<K,V> xp = p;
2793 >                        TreeNode<K,V> xp = p;
2794                          if ((p = (dir <= 0) ? p.left : p.right) == null) {
2795                              x.parent = xp;
2796                              if (dir <= 0)
# Line 2809 | Line 2853 | public class ConcurrentHashMap<K,V> exte
2853           */
2854          final Node<K,V> find(int h, Object k) {
2855              if (k != null) {
2856 <                for (Node<K,V> e = first; e != null; e = e.next) {
2856 >                for (Node<K,V> e = first; e != null; ) {
2857                      int s; K ek;
2858                      if (((s = lockState) & (WAITER|WRITER)) != 0) {
2859                          if (e.hash == h &&
2860                              ((ek = e.key) == k || (ek != null && k.equals(ek))))
2861                              return e;
2862 +                        e = e.next;
2863                      }
2864                      else if (U.compareAndSwapInt(this, LOCKSTATE, s,
2865                                                   s + READER)) {
# Line 3098 | Line 3143 | public class ConcurrentHashMap<K,V> exte
3143  
3144          static <K,V> TreeNode<K,V> balanceDeletion(TreeNode<K,V> root,
3145                                                     TreeNode<K,V> x) {
3146 <            for (TreeNode<K,V> xp, xpl, xpr;;)  {
3146 >            for (TreeNode<K,V> xp, xpl, xpr;;) {
3147                  if (x == null || x == root)
3148                      return root;
3149                  else if ((xp = x.parent) == null) {
# Line 3213 | Line 3258 | public class ConcurrentHashMap<K,V> exte
3258              return true;
3259          }
3260  
3261 <        private static final sun.misc.Unsafe U;
3261 >        private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
3262          private static final long LOCKSTATE;
3263          static {
3264              try {
3220                U = sun.misc.Unsafe.getUnsafe();
3221                Class<?> k = TreeBin.class;
3265                  LOCKSTATE = U.objectFieldOffset
3266 <                    (k.getDeclaredField("lockState"));
3267 <            } catch (Exception e) {
3266 >                    (TreeBin.class.getDeclaredField("lockState"));
3267 >            } catch (ReflectiveOperationException e) {
3268                  throw new Error(e);
3269              }
3270          }
# Line 3450 | Line 3493 | public class ConcurrentHashMap<K,V> exte
3493          public K getKey()        { return key; }
3494          public V getValue()      { return val; }
3495          public int hashCode()    { return key.hashCode() ^ val.hashCode(); }
3496 <        public String toString() { return key + "=" + val; }
3496 >        public String toString() {
3497 >            return Helpers.mapEntryToString(key, val);
3498 >        }
3499  
3500          public boolean equals(Object o) {
3501              Object k, v; Map.Entry<?,?> e;
# Line 4663 | Line 4708 | public class ConcurrentHashMap<K,V> exte
4708              throw new UnsupportedOperationException();
4709          }
4710  
4711 +        public boolean removeIf(Predicate<? super V> filter) {
4712 +            return map.removeValueIf(filter);
4713 +        }
4714 +
4715          public Spliterator<V> spliterator() {
4716              Node<K,V>[] t;
4717              ConcurrentHashMap<K,V> m = map;
# Line 4732 | Line 4781 | public class ConcurrentHashMap<K,V> exte
4781              return added;
4782          }
4783  
4784 +        public boolean removeIf(Predicate<? super Entry<K,V>> filter) {
4785 +            return map.removeEntryIf(filter);
4786 +        }
4787 +
4788          public final int hashCode() {
4789              int h = 0;
4790              Node<K,V>[] t;
# Line 6248 | Line 6301 | public class ConcurrentHashMap<K,V> exte
6301      }
6302  
6303      // Unsafe mechanics
6304 <    private static final sun.misc.Unsafe U;
6304 >    private static final sun.misc.Unsafe U = sun.misc.Unsafe.getUnsafe();
6305      private static final long SIZECTL;
6306      private static final long TRANSFERINDEX;
6307      private static final long BASECOUNT;
6308      private static final long CELLSBUSY;
6309      private static final long CELLVALUE;
6310 <    private static final long ABASE;
6310 >    private static final int ABASE;
6311      private static final int ASHIFT;
6312  
6313      static {
6314          try {
6262            U = sun.misc.Unsafe.getUnsafe();
6263            Class<?> k = ConcurrentHashMap.class;
6315              SIZECTL = U.objectFieldOffset
6316 <                (k.getDeclaredField("sizeCtl"));
6316 >                (ConcurrentHashMap.class.getDeclaredField("sizeCtl"));
6317              TRANSFERINDEX = U.objectFieldOffset
6318 <                (k.getDeclaredField("transferIndex"));
6318 >                (ConcurrentHashMap.class.getDeclaredField("transferIndex"));
6319              BASECOUNT = U.objectFieldOffset
6320 <                (k.getDeclaredField("baseCount"));
6320 >                (ConcurrentHashMap.class.getDeclaredField("baseCount"));
6321              CELLSBUSY = U.objectFieldOffset
6322 <                (k.getDeclaredField("cellsBusy"));
6323 <            Class<?> ck = CounterCell.class;
6322 >                (ConcurrentHashMap.class.getDeclaredField("cellsBusy"));
6323 >
6324              CELLVALUE = U.objectFieldOffset
6325 <                (ck.getDeclaredField("value"));
6326 <            Class<?> ak = Node[].class;
6327 <            ABASE = U.arrayBaseOffset(ak);
6328 <            int scale = U.arrayIndexScale(ak);
6325 >                (CounterCell.class.getDeclaredField("value"));
6326 >
6327 >            ABASE = U.arrayBaseOffset(Node[].class);
6328 >            int scale = U.arrayIndexScale(Node[].class);
6329              if ((scale & (scale - 1)) != 0)
6330 <                throw new Error("data type scale not a power of two");
6330 >                throw new Error("array index scale not a power of two");
6331              ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
6332 <        } catch (Exception e) {
6332 >        } catch (ReflectiveOperationException e) {
6333              throw new Error(e);
6334          }
6335 +
6336 +        // Reduce the risk of rare disastrous classloading in first call to
6337 +        // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
6338 +        Class<?> ensureLoaded = LockSupport.class;
6339      }
6340   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines