Mercurial > hg > release > icedtea7-forest-2.1 > jdk
changeset 4873:5b067978a725
8009063: Improve reliability of ConcurrentHashMap
Reviewed-by: alanb, ahgross
author | andrew |
---|---|
date | Wed, 17 Apr 2013 23:16:21 +0100 |
parents | ba3e07024008 |
children | 8abc50bce580 |
files | src/share/classes/java/util/concurrent/ConcurrentHashMap.java |
diffstat | 1 files changed, 27 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/java/util/concurrent/ConcurrentHashMap.java Fri Mar 01 03:50:17 2013 +0400 +++ b/src/share/classes/java/util/concurrent/ConcurrentHashMap.java Wed Apr 17 23:16:21 2013 +0100 @@ -40,6 +40,7 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.io.ObjectStreamField; /** * A hash table supporting full concurrency of retrievals and @@ -1470,7 +1471,23 @@ @SuppressWarnings("unchecked") private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException { - s.defaultReadObject(); + // Don't call defaultReadObject() + ObjectInputStream.GetField oisFields = s.readFields(); + final Segment<K,V>[] oisSegments = (Segment<K,V>[])oisFields.get("segments", null); + + final int ssize = oisSegments.length; + if (ssize < 1 || ssize > MAX_SEGMENTS + || (ssize & (ssize-1)) != 0 ) // ssize not power of two + throw new java.io.InvalidObjectException("Bad number of segments:" + + ssize); + int sshift = 0, ssizeTmp = ssize; + while (ssizeTmp > 1) { + ++sshift; + ssizeTmp >>>= 1; + } + UNSAFE.putIntVolatile(this, SEGSHIFT_OFFSET, 32 - sshift); + UNSAFE.putIntVolatile(this, SEGMASK_OFFSET, ssize - 1); + UNSAFE.putObjectVolatile(this, SEGMENTS_OFFSET, oisSegments); // Re-initialize segments to be minimally sized, and let grow. int cap = MIN_SEGMENT_TABLE_CAPACITY; @@ -1499,6 +1516,9 @@ private static final int SSHIFT; private static final long TBASE; private static final int TSHIFT; + private static final long SEGSHIFT_OFFSET; + private static final long SEGMASK_OFFSET; + private static final long SEGMENTS_OFFSET; static { int ss, ts; @@ -1510,6 +1530,12 @@ SBASE = UNSAFE.arrayBaseOffset(sc); ts = UNSAFE.arrayIndexScale(tc); ss = UNSAFE.arrayIndexScale(sc); + SEGSHIFT_OFFSET = UNSAFE.objectFieldOffset( + ConcurrentHashMap.class.getDeclaredField("segmentShift")); + SEGMASK_OFFSET = UNSAFE.objectFieldOffset( + ConcurrentHashMap.class.getDeclaredField("segmentMask")); + SEGMENTS_OFFSET = UNSAFE.objectFieldOffset( + ConcurrentHashMap.class.getDeclaredField("segments")); } catch (Exception e) { throw new Error(e); }