From 5a3bbd9ad173d4973568950bdcd31a332cbb88ac Mon Sep 17 00:00:00 2001 From: chegar Date: Sun, 3 Mar 2013 10:07:52 +0000 Subject: [PATCH] 8009063: Improve reliability of ConcurrentHashMap Reviewed-by: alanb, ahgross --- .../util/concurrent/ConcurrentHashMap.java | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/share/classes/java/util/concurrent/ConcurrentHashMap.java b/src/share/classes/java/util/concurrent/ConcurrentHashMap.java index 66ae51667..b7c8bde6b 100644 --- a/src/share/classes/java/util/concurrent/ConcurrentHashMap.java +++ b/src/share/classes/java/util/concurrent/ConcurrentHashMap.java @@ -34,6 +34,7 @@ */ package java.util.concurrent; +import java.io.ObjectInputStream; import java.util.concurrent.locks.*; import java.util.*; import java.io.Serializable; @@ -1483,7 +1484,23 @@ public class ConcurrentHashMap extends AbstractMap @SuppressWarnings("unchecked") private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { - s.defaultReadObject(); + // Don't call defaultReadObject() + ObjectInputStream.GetField oisFields = s.readFields(); + final Segment[] oisSegments = (Segment[])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); // set hashMask UNSAFE.putIntVolatile(this, HASHSEED_OFFSET, @@ -1517,6 +1534,9 @@ public class ConcurrentHashMap extends AbstractMap private static final long TBASE; private static final int TSHIFT; private static final long HASHSEED_OFFSET; + private static final long SEGSHIFT_OFFSET; + private static final long SEGMASK_OFFSET; + private static final long SEGMENTS_OFFSET; static { int ss, ts; @@ -1530,6 +1550,12 @@ public class ConcurrentHashMap extends AbstractMap ss = UNSAFE.arrayIndexScale(sc); HASHSEED_OFFSET = UNSAFE.objectFieldOffset( ConcurrentHashMap.class.getDeclaredField("hashSeed")); + 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); } -- GitLab