185 * |
185 * |
186 * @see ConcurrentModificationException |
186 * @see ConcurrentModificationException |
187 */ |
187 */ |
188 int modCount; |
188 int modCount; |
189 |
189 |
|
190 private static class Holder { |
|
191 static final boolean USE_HASHSEED; |
|
192 |
|
193 static { |
|
194 String hashSeedProp = java.security.AccessController.doPrivileged( |
|
195 new sun.security.action.GetPropertyAction( |
|
196 "jdk.map.useRandomSeed")); |
|
197 boolean localBool = (null != hashSeedProp) |
|
198 ? Boolean.parseBoolean(hashSeedProp) : false; |
|
199 USE_HASHSEED = localBool; |
|
200 } |
|
201 } |
|
202 |
190 /** |
203 /** |
191 * A randomizing value associated with this instance that is applied to |
204 * A randomizing value associated with this instance that is applied to |
192 * hash code of keys to make hash collisions harder to find. |
205 * hash code of keys to make hash collisions harder to find. |
193 */ |
206 * |
194 transient final int hashSeed = sun.misc.Hashing.randomHashSeed(this); |
207 * Non-final so it can be set lazily, but be sure not to set more than once. |
|
208 */ |
|
209 transient int hashSeed; |
|
210 |
|
211 /** |
|
212 * Initialize the hashing mask value. |
|
213 */ |
|
214 final void initHashSeed() { |
|
215 if (sun.misc.VM.isBooted() && Holder.USE_HASHSEED) { |
|
216 // Do not set hashSeed more than once! |
|
217 // assert hashSeed == 0; |
|
218 hashSeed = sun.misc.Hashing.randomHashSeed(this); |
|
219 } |
|
220 } |
195 |
221 |
196 @SuppressWarnings("unchecked") |
222 @SuppressWarnings("unchecked") |
197 private Entry<K,V>[] newTable(int n) { |
223 private Entry<K,V>[] newTable(int n) { |
198 return (Entry<K,V>[]) new Entry<?,?>[n]; |
224 return (Entry<K,V>[]) new Entry<?,?>[n]; |
199 } |
225 } |
221 while (capacity < initialCapacity) |
247 while (capacity < initialCapacity) |
222 capacity <<= 1; |
248 capacity <<= 1; |
223 table = newTable(capacity); |
249 table = newTable(capacity); |
224 this.loadFactor = loadFactor; |
250 this.loadFactor = loadFactor; |
225 threshold = (int)(capacity * loadFactor); |
251 threshold = (int)(capacity * loadFactor); |
|
252 initHashSeed(); |
226 } |
253 } |
227 |
254 |
228 /** |
255 /** |
229 * Constructs a new, empty <tt>WeakHashMap</tt> with the given initial |
256 * Constructs a new, empty <tt>WeakHashMap</tt> with the given initial |
230 * capacity and the default load factor (0.75). |
257 * capacity and the default load factor (0.75). |
296 * critical because HashMap uses power-of-two length hash tables, that |
323 * critical because HashMap uses power-of-two length hash tables, that |
297 * otherwise encounter collisions for hashCodes that do not differ |
324 * otherwise encounter collisions for hashCodes that do not differ |
298 * in lower bits. |
325 * in lower bits. |
299 */ |
326 */ |
300 final int hash(Object k) { |
327 final int hash(Object k) { |
301 if (k instanceof String) { |
328 int h = hashSeed ^ k.hashCode(); |
302 return ((String) k).hash32(); |
|
303 } |
|
304 int h = hashSeed ^ k.hashCode(); |
|
305 |
329 |
306 // This function ensures that hashCodes that differ only by |
330 // This function ensures that hashCodes that differ only by |
307 // constant multiples at each bit position have a bounded |
331 // constant multiples at each bit position have a bounded |
308 // number of collisions (approximately 8 at default load factor). |
332 // number of collisions (approximately 8 at default load factor). |
309 h ^= (h >>> 20) ^ (h >>> 12); |
333 h ^= (h >>> 20) ^ (h >>> 12); |