首页

参考springframework的ConcurrentReferenceHashMap实现java.util.concurrent.ConcurrentMap接口

标签:ConcurrentReferenceHashMap,并发,springframework     发布时间:2017-12-11   

一、前言

基于springframework的org.springframework.util.ConcurrentReferenceHashMap的类似java.util.concurrent.ConcurrentHashMap的实现java.util.concurrent.ConcurrentMap接口和java.util.AbstractMap抽象类。

二、源码说明

package org.springframework.util;@b@@b@import java.lang.ref.ReferenceQueue;@b@import java.lang.ref.SoftReference;@b@import java.lang.ref.WeakReference;@b@import java.lang.reflect.Array;@b@import java.util.AbstractMap;@b@import java.util.AbstractSet;@b@import java.util.Collections;@b@import java.util.EnumSet;@b@import java.util.HashSet;@b@import java.util.Iterator;@b@import java.util.Map.Entry;@b@import java.util.NoSuchElementException;@b@import java.util.Set;@b@import java.util.concurrent.ConcurrentMap;@b@import java.util.concurrent.locks.ReentrantLock;@b@@b@public class ConcurrentReferenceHashMap<K, V> extends AbstractMap<K, V>@b@  implements ConcurrentMap<K, V>@b@{@b@  private static final int DEFAULT_INITIAL_CAPACITY = 16;@b@  private static final float DEFAULT_LOAD_FACTOR = 0.75F;@b@  private static final int DEFAULT_CONCURRENCY_LEVEL = 16;@b@  private static final ReferenceType DEFAULT_REFERENCE_TYPE = ReferenceType.SOFT;@b@  private static final int MAXIMUM_CONCURRENCY_LEVEL = 65536;@b@  private static final int MAXIMUM_SEGMENT_SIZE = 1073741824;@b@  private final ConcurrentReferenceHashMap<K, V>[].Segment[] segments;@b@  private final float loadFactor;@b@  private final ReferenceType referenceType;@b@  private final int shift;@b@  private Set<Map.Entry<K, V>> entrySet;@b@@b@  public ConcurrentReferenceHashMap()@b@  {@b@    this(16, 0.75F, 16, DEFAULT_REFERENCE_TYPE);@b@  }@b@@b@  public ConcurrentReferenceHashMap(int initialCapacity)@b@  {@b@    this(initialCapacity, 0.75F, 16, DEFAULT_REFERENCE_TYPE);@b@  }@b@@b@  public ConcurrentReferenceHashMap(int initialCapacity, float loadFactor)@b@  {@b@    this(initialCapacity, loadFactor, 16, DEFAULT_REFERENCE_TYPE);@b@  }@b@@b@  public ConcurrentReferenceHashMap(int initialCapacity, int concurrencyLevel)@b@  {@b@    this(initialCapacity, 0.75F, concurrencyLevel, DEFAULT_REFERENCE_TYPE);@b@  }@b@@b@  public ConcurrentReferenceHashMap(int initialCapacity, ReferenceType referenceType)@b@  {@b@    this(initialCapacity, 0.75F, 16, referenceType);@b@  }@b@@b@  public ConcurrentReferenceHashMap(int initialCapacity, float loadFactor, int concurrencyLevel)@b@  {@b@    this(initialCapacity, loadFactor, concurrencyLevel, DEFAULT_REFERENCE_TYPE);@b@  }@b@@b@  public ConcurrentReferenceHashMap(int initialCapacity, float loadFactor, int concurrencyLevel, ReferenceType referenceType)@b@  {@b@    Assert.isTrue(initialCapacity >= 0, "Initial capacity must not be negative");@b@    Assert.isTrue(loadFactor > 0.0F, "Load factor must be positive");@b@    Assert.isTrue(concurrencyLevel > 0, "Concurrency level must be positive");@b@    Assert.notNull(referenceType, "Reference type must not be null");@b@    this.loadFactor = loadFactor;@b@    this.shift = calculateShift(concurrencyLevel, 65536);@b@    int size = 1 << this.shift;@b@    this.referenceType = referenceType;@b@    int roundedUpSegmentCapacity = (int)((initialCapacity + size - 1L) / size);@b@    this.segments = ((Segment[])(Segment[])Array.newInstance(Segment.class, size));@b@    for (int i = 0; i < this.segments.length; ++i)@b@      this.segments[i] = new Segment(this, roundedUpSegmentCapacity);@b@  }@b@@b@  protected final float getLoadFactor()@b@  {@b@    return this.loadFactor;@b@  }@b@@b@  protected final int getSegmentsSize() {@b@    return this.segments.length;@b@  }@b@@b@  protected final ConcurrentReferenceHashMap<K, V>.Segment getSegment(int index) {@b@    return this.segments[index];@b@  }@b@@b@  protected ConcurrentReferenceHashMap<K, V>.ReferenceManager createReferenceManager()@b@  {@b@    return new ReferenceManager(this);@b@  }@b@@b@  protected int getHash(Object o)@b@  {@b@    int hash = (o == null) ? 0 : o.hashCode();@b@    hash += (hash << 15 ^ 0xFFFFCD7D);@b@    hash ^= hash >>> 10;@b@    hash += (hash << 3);@b@    hash ^= hash >>> 6;@b@    hash += (hash << 2) + (hash << 14);@b@    hash ^= hash >>> 16;@b@    return hash;@b@  }@b@@b@  public V get(Object key)@b@  {@b@    Reference reference = getReference(key, Restructure.WHEN_NECESSARY);@b@    Entry entry = (reference != null) ? reference.get() : null;@b@    return ((entry != null) ? entry.getValue() : null);@b@  }@b@@b@  public boolean containsKey(Object key)@b@  {@b@    Reference reference = getReference(key, Restructure.WHEN_NECESSARY);@b@    Entry entry = (reference != null) ? reference.get() : null;@b@    return ((entry != null) && (ObjectUtils.nullSafeEquals(entry.getKey(), key)));@b@  }@b@@b@  protected final Reference<K, V> getReference(Object key, Restructure restructure)@b@  {@b@    int hash = getHash(key);@b@    return getSegmentForHash(hash).getReference(key, hash, restructure);@b@  }@b@@b@  public V put(K key, V value)@b@  {@b@    return put(key, value, true);@b@  }@b@@b@  public V putIfAbsent(K key, V value)@b@  {@b@    return put(key, value, false);@b@  }@b@@b@  private V put(K key, V value, boolean overwriteExisting) {@b@    return doTask(key, new Task(this, new TaskOption[] { TaskOption.RESTRUCTURE_BEFORE, TaskOption.RESIZE }, overwriteExisting, value)@b@    {@b@      protected V execute(, ConcurrentReferenceHashMap.Entry<K, V> entry, ConcurrentReferenceHashMap<K, V>.Entries entries) {@b@        if (entry != null) {@b@          Object previousValue = entry.getValue();@b@          if (this.val$overwriteExisting)@b@            entry.setValue(this.val$value);@b@@b@          return previousValue;@b@        }@b@        entries.add(this.val$value);@b@        return null;@b@      }@b@    });@b@  }@b@@b@  public V remove(Object key)@b@  {@b@    return doTask(key, new Task(this, new TaskOption[] { TaskOption.RESTRUCTURE_AFTER, TaskOption.SKIP_IF_EMPTY })@b@    {@b@      protected V execute(, ConcurrentReferenceHashMap.Entry<K, V> entry) {@b@        if (entry != null) {@b@          reference.release();@b@          return ConcurrentReferenceHashMap.Entry.access$000(entry);@b@        }@b@        return null;@b@      }@b@    });@b@  }@b@@b@  public boolean remove(Object key, Object value)@b@  {@b@    return ((Boolean)doTask(key, new Task(this, new TaskOption[] { TaskOption.RESTRUCTURE_AFTER, TaskOption.SKIP_IF_EMPTY }, value)@b@    {@b@      protected Boolean execute(, ConcurrentReferenceHashMap.Entry<K, V> entry) {@b@        if ((entry != null) && (ObjectUtils.nullSafeEquals(entry.getValue(), this.val$value))) {@b@          reference.release();@b@          return Boolean.valueOf(true);@b@        }@b@        return Boolean.valueOf(false);@b@      }@b@    })).booleanValue();@b@  }@b@@b@  public boolean replace(K key, V oldValue, V newValue)@b@  {@b@    return ((Boolean)doTask(key, new Task(this, new TaskOption[] { TaskOption.RESTRUCTURE_BEFORE, TaskOption.SKIP_IF_EMPTY }, oldValue, newValue)@b@    {@b@      protected Boolean execute(, ConcurrentReferenceHashMap.Entry<K, V> entry) {@b@        if ((entry != null) && (ObjectUtils.nullSafeEquals(entry.getValue(), this.val$oldValue))) {@b@          entry.setValue(this.val$newValue);@b@          return Boolean.valueOf(true);@b@        }@b@        return Boolean.valueOf(false);@b@      }@b@    })).booleanValue();@b@  }@b@@b@  public V replace(K key, V value)@b@  {@b@    return doTask(key, new Task(this, new TaskOption[] { TaskOption.RESTRUCTURE_BEFORE, TaskOption.SKIP_IF_EMPTY }, value)@b@    {@b@      protected V execute(, ConcurrentReferenceHashMap.Entry<K, V> entry) {@b@        if (entry != null) {@b@          Object previousValue = entry.getValue();@b@          entry.setValue(this.val$value);@b@          return previousValue;@b@        }@b@        return null;@b@      }@b@    });@b@  }@b@@b@  public void clear()@b@  {@b@    Segment[] arrayOfSegment = this.segments; int i = arrayOfSegment.length; for (int j = 0; j < i; ++j) { Segment segment = arrayOfSegment[j];@b@      segment.clear();@b@    }@b@  }@b@@b@  public void purgeUnreferencedEntries()@b@  {@b@    Segment[] arrayOfSegment = this.segments; int i = arrayOfSegment.length; for (int j = 0; j < i; ++j) { Segment segment = arrayOfSegment[j];@b@      segment.restructureIfNecessary(false);@b@    }@b@  }@b@@b@  public int size()@b@  {@b@    int size = 0;@b@    Segment[] arrayOfSegment = this.segments; int i = arrayOfSegment.length; for (int j = 0; j < i; ++j) { Segment segment = arrayOfSegment[j];@b@      size += segment.getCount();@b@    }@b@    return size;@b@  }@b@@b@  public Set<Map.Entry<K, V>> entrySet()@b@  {@b@    if (this.entrySet == null)@b@      this.entrySet = new EntrySet(this, null);@b@@b@    return this.entrySet;@b@  }@b@@b@  private <T> T doTask(Object key, ConcurrentReferenceHashMap<K, V>.Task<T> task) {@b@    int hash = getHash(key);@b@    return getSegmentForHash(hash).doTask(hash, key, task);@b@  }@b@@b@  private ConcurrentReferenceHashMap<K, V>.Segment getSegmentForHash(int hash) {@b@    return this.segments[(hash >>> 32 - this.shift & this.segments.length - 1)];@b@  }@b@@b@  protected static int calculateShift(int minimumValue, int maximumValue)@b@  {@b@    int shift = 0;@b@    int value = 1;@b@    while ((value < minimumValue) && (value < maximumValue)) {@b@      value <<= 1;@b@      ++shift;@b@    }@b@    return shift;@b@  }@b@@b@  private static final class WeakEntryReference<K, V> extends WeakReference<ConcurrentReferenceHashMap.Entry<K, V>>@b@    implements ConcurrentReferenceHashMap.Reference<K, V>@b@  {@b@    private final int hash;@b@    private final ConcurrentReferenceHashMap.Reference<K, V> nextReference;@b@@b@    public WeakEntryReference(ConcurrentReferenceHashMap.Entry<K, V> entry, int hash, ConcurrentReferenceHashMap.Reference<K, V> next, ReferenceQueue<ConcurrentReferenceHashMap.Entry<K, V>> queue)@b@    {@b@      super(entry, queue);@b@      this.hash = hash;@b@      this.nextReference = next;@b@    }@b@@b@    public int getHash()@b@    {@b@      return this.hash;@b@    }@b@@b@    public ConcurrentReferenceHashMap.Reference<K, V> getNext()@b@    {@b@      return this.nextReference;@b@    }@b@@b@    public void release()@b@    {@b@      enqueue();@b@      clear();@b@    }@b@  }@b@@b@  private static final class SoftEntryReference<K, V> extends SoftReference<ConcurrentReferenceHashMap.Entry<K, V>>@b@    implements ConcurrentReferenceHashMap.Reference<K, V>@b@  {@b@    private final int hash;@b@    private final ConcurrentReferenceHashMap.Reference<K, V> nextReference;@b@@b@    public SoftEntryReference(ConcurrentReferenceHashMap.Entry<K, V> entry, int hash, ConcurrentReferenceHashMap.Reference<K, V> next, ReferenceQueue<ConcurrentReferenceHashMap.Entry<K, V>> queue)@b@    {@b@      super(entry, queue);@b@      this.hash = hash;@b@      this.nextReference = next;@b@    }@b@@b@    public int getHash()@b@    {@b@      return this.hash;@b@    }@b@@b@    public ConcurrentReferenceHashMap.Reference<K, V> getNext()@b@    {@b@      return this.nextReference;@b@    }@b@@b@    public void release()@b@    {@b@      enqueue();@b@      clear();@b@    }@b@  }@b@@b@  protected class ReferenceManager@b@  {@b@    private final ReferenceQueue<ConcurrentReferenceHashMap.Entry<K, V>> queue;@b@@b@    protected ReferenceManager()@b@    {@b@      this.queue = new ReferenceQueue();@b@    }@b@@b@    public ConcurrentReferenceHashMap.Reference<K, V> createReference(, int hash, ConcurrentReferenceHashMap.Reference<K, V> next)@b@    {@b@      if (ConcurrentReferenceHashMap.access$700(this.this$0) == ConcurrentReferenceHashMap.ReferenceType.WEAK)@b@        return new ConcurrentReferenceHashMap.WeakEntryReference(entry, hash, next, this.queue);@b@@b@      return new ConcurrentReferenceHashMap.SoftEntryReference(entry, hash, next, this.queue);@b@    }@b@@b@    public ConcurrentReferenceHashMap.Reference<K, V> pollForPurge()@b@    {@b@      return ((ConcurrentReferenceHashMap.Reference)this.queue.poll());@b@    }@b@  }@b@@b@  protected static enum Restructure@b@  {@b@    WHEN_NECESSARY, NEVER;@b@  }@b@@b@  private class EntryIterator@b@    implements Iterator<Map.Entry<K, V>>@b@  {@b@    private int segmentIndex;@b@    private int referenceIndex;@b@    private ConcurrentReferenceHashMap.Reference<K, V>[] references;@b@    private ConcurrentReferenceHashMap.Reference<K, V> reference;@b@    private ConcurrentReferenceHashMap.Entry<K, V> next;@b@    private ConcurrentReferenceHashMap.Entry<K, V> last;@b@@b@    public EntryIterator()@b@    {@b@      moveToNextSegment();@b@    }@b@@b@    public boolean hasNext()@b@    {@b@      getNextIfNecessary();@b@      return (this.next != null);@b@    }@b@@b@    public ConcurrentReferenceHashMap.Entry<K, V> next()@b@    {@b@      getNextIfNecessary();@b@      if (this.next == null)@b@        throw new NoSuchElementException();@b@@b@      this.last = this.next;@b@      this.next = null;@b@      return this.last;@b@    }@b@@b@    private void getNextIfNecessary() {@b@      while (this.next == null) {@b@        moveToNextReference();@b@        if (this.reference == null)@b@          return;@b@@b@        this.next = this.reference.get();@b@      }@b@    }@b@@b@    private void moveToNextReference() {@b@      if (this.reference != null)@b@        this.reference = this.reference.getNext(); while (true) {@b@        while (true) {@b@          if ((this.reference != null) || (this.references == null)) return;@b@          if (this.referenceIndex < this.references.length) break;@b@          moveToNextSegment();@b@          this.referenceIndex = 0;@b@        }@b@@b@        this.reference = this.references[this.referenceIndex];@b@        this.referenceIndex += 1;@b@      }@b@    }@b@@b@    private void moveToNextSegment()@b@    {@b@      this.reference = null;@b@      this.references = null;@b@      if (this.segmentIndex < ConcurrentReferenceHashMap.access$600(this.this$0).length) {@b@        this.references = ConcurrentReferenceHashMap.Segment.access$400(ConcurrentReferenceHashMap.access$600(this.this$0)[this.segmentIndex]);@b@        this.segmentIndex += 1;@b@      }@b@    }@b@@b@    public void remove()@b@    {@b@      Assert.state(this.last != null);@b@      this.this$0.remove(this.last.getKey());@b@    }@b@  }@b@@b@  private class EntrySet extends AbstractSet<Map.Entry<K, V>>@b@  {@b@    public Iterator<Map.Entry<K, V>> iterator()@b@    {@b@      return new ConcurrentReferenceHashMap.EntryIterator(this.this$0);@b@    }@b@@b@    public boolean contains()@b@    {@b@      if ((o != null) && (o instanceof Map.Entry)) {@b@        Map.Entry entry = (Map.Entry)o;@b@        ConcurrentReferenceHashMap.Reference reference = this.this$0.getReference(entry.getKey(), ConcurrentReferenceHashMap.Restructure.NEVER);@b@        ConcurrentReferenceHashMap.Entry other = (reference != null) ? reference.get() : null;@b@        if (other != null)@b@          return ObjectUtils.nullSafeEquals(entry.getValue(), other.getValue());@b@      }@b@@b@      return false;@b@    }@b@@b@    public boolean remove()@b@    {@b@      if (o instanceof Map.Entry) {@b@        Map.Entry entry = (Map.Entry)o;@b@        return this.this$0.remove(entry.getKey(), entry.getValue());@b@      }@b@      return false;@b@    }@b@@b@    public int size()@b@    {@b@      return this.this$0.size();@b@    }@b@@b@    public void clear()@b@    {@b@      this.this$0.clear();@b@    }@b@  }@b@@b@  private abstract class Entries@b@  {@b@    public abstract void add();@b@  }@b@@b@  private static enum TaskOption@b@  {@b@    RESTRUCTURE_BEFORE, RESTRUCTURE_AFTER, SKIP_IF_EMPTY, RESIZE;@b@  }@b@@b@  private abstract class Task<T>@b@  {@b@    private final EnumSet<ConcurrentReferenceHashMap.TaskOption> options;@b@@b@    public Task(, ConcurrentReferenceHashMap.TaskOption[] paramArrayOfTaskOption)@b@    {@b@      this.options = ((options.length == 0) ? EnumSet.noneOf(ConcurrentReferenceHashMap.TaskOption.class) : EnumSet.of(options[0], options));@b@    }@b@@b@    public boolean hasOption() {@b@      return this.options.contains(option);@b@    }@b@@b@    protected T execute(, ConcurrentReferenceHashMap.Entry<K, V> entry, ConcurrentReferenceHashMap<K, V>.Entries entries)@b@    {@b@      return execute(reference, entry);@b@    }@b@@b@    protected T execute(, ConcurrentReferenceHashMap.Entry<K, V> entry)@b@    {@b@      return null;@b@    }@b@  }@b@@b@  protected static final class Entry<K, V>@b@    implements Map.Entry<K, V>@b@  {@b@    private final K key;@b@    private volatile V value;@b@@b@    public Entry(K key, V value)@b@    {@b@      this.key = key;@b@      this.value = value;@b@    }@b@@b@    public K getKey()@b@    {@b@      return this.key;@b@    }@b@@b@    public V getValue()@b@    {@b@      return this.value;@b@    }@b@@b@    public V setValue(V value)@b@    {@b@      Object previous = this.value;@b@      this.value = value;@b@      return previous;@b@    }@b@@b@    public String toString()@b@    {@b@      return this.key + "=" + this.value;@b@    }@b@@b@    public final boolean equals(Object other)@b@    {@b@      if (this == other)@b@        return true;@b@@b@      if (!(other instanceof Map.Entry))@b@        return false;@b@@b@      Map.Entry otherEntry = (Map.Entry)other;@b@@b@      return ((ObjectUtils.nullSafeEquals(getKey(), otherEntry.getKey())) && @b@        (ObjectUtils.nullSafeEquals(getValue(), otherEntry.getValue())));@b@    }@b@@b@    public final int hashCode()@b@    {@b@      return (ObjectUtils.nullSafeHashCode(this.key) ^ ObjectUtils.nullSafeHashCode(this.value));@b@    }@b@  }@b@@b@  protected static abstract interface Reference<K, V>@b@  {@b@    public abstract ConcurrentReferenceHashMap.Entry<K, V> get();@b@@b@    public abstract int getHash();@b@@b@    public abstract Reference<K, V> getNext();@b@@b@    public abstract void release();@b@  }@b@@b@  protected final class Segment extends ReentrantLock@b@  {@b@    private final ConcurrentReferenceHashMap<K, V>.ReferenceManager referenceManager;@b@    private final int initialSize;@b@    private volatile ConcurrentReferenceHashMap.Reference<K, V>[] references;@b@    private volatile int count = 0;@b@    private int resizeThreshold;@b@@b@    public Segment(, int initialCapacity)@b@    {@b@      this.referenceManager = this$0.createReferenceManager();@b@      this.initialSize = (1 << ConcurrentReferenceHashMap.calculateShift(initialCapacity, 1073741824));@b@      setReferences(createReferenceArray(this.initialSize));@b@    }@b@@b@    public ConcurrentReferenceHashMap.Reference<K, V> getReference(, int hash, ConcurrentReferenceHashMap.Restructure restructure) {@b@      if (restructure == ConcurrentReferenceHashMap.Restructure.WHEN_NECESSARY)@b@        restructureIfNecessary(false);@b@@b@      if (this.count == 0) {@b@        return null;@b@      }@b@@b@      ConcurrentReferenceHashMap.Reference[] references = this.references;@b@      int index = getIndex(hash, references);@b@      ConcurrentReferenceHashMap.Reference head = references[index];@b@      return findInChain(head, key, hash);@b@    }@b@@b@    public <T> T doTask(, Object key, ConcurrentReferenceHashMap<K, V>.Task<T> task)@b@    {@b@      boolean resize = task.hasOption(ConcurrentReferenceHashMap.TaskOption.RESIZE);@b@      if (task.hasOption(ConcurrentReferenceHashMap.TaskOption.RESTRUCTURE_BEFORE))@b@        restructureIfNecessary(resize);@b@@b@      if ((task.hasOption(ConcurrentReferenceHashMap.TaskOption.SKIP_IF_EMPTY)) && (this.count == 0))@b@        return task.execute(null, null, null);@b@@b@      lock();@b@      try {@b@        int index = getIndex(hash, this.references);@b@        ConcurrentReferenceHashMap.Reference head = this.references[index];@b@        ConcurrentReferenceHashMap.Reference reference = findInChain(head, key, hash);@b@        ConcurrentReferenceHashMap.Entry entry = (reference != null) ? reference.get() : null;@b@        ConcurrentReferenceHashMap.Entries entries = new ConcurrentReferenceHashMap.Entries(this, key, hash, head, index)@b@        {@b@          public void add()@b@          {@b@            ConcurrentReferenceHashMap.Entry newEntry = new ConcurrentReferenceHashMap.Entry(this.val$key, value);@b@            ConcurrentReferenceHashMap.Reference newReference = ConcurrentReferenceHashMap.Segment.access$300(this.this$1).createReference(newEntry, this.val$hash, this.val$head);@b@            ConcurrentReferenceHashMap.Segment.access$400(this.this$1)[this.val$index] = newReference;@b@            ConcurrentReferenceHashMap.Segment.access$508(this.this$1);@b@          }@b@@b@        };@b@        Object localObject1 = task.execute(reference, entry, entries);@b@@b@        return localObject1;@b@      }@b@      finally@b@      {@b@        unlock();@b@        if (task.hasOption(ConcurrentReferenceHashMap.TaskOption.RESTRUCTURE_AFTER))@b@          restructureIfNecessary(resize);  }  } @b@    // ERROR //@b@    public void clear() { // Byte code:@b@      //   0: aload_0@b@      //   1: getfield 2	org/springframework/util/ConcurrentReferenceHashMap$Segment:count	I@b@      //   4: ifne +4 -> 8@b@      //   7: return@b@      //   8: aload_0@b@      //   9: invokevirtual 22	org/springframework/util/ConcurrentReferenceHashMap$Segment:lock	()V@b@      //   12: aload_0@b@      //   13: aload_0@b@      //   14: aload_0@b@      //   15: getfield 10	org/springframework/util/ConcurrentReferenceHashMap$Segment:initialSize	I@b@      //   18: invokespecial 11	org/springframework/util/ConcurrentReferenceHashMap$Segment:createReferenceArray	(I)[Lorg/springframework/util/ConcurrentReferenceHashMap$Reference;@b@      //   21: invokespecial 12	org/springframework/util/ConcurrentReferenceHashMap$Segment:setReferences	([Lorg/springframework/util/ConcurrentReferenceHashMap$Reference;)V@b@      //   24: aload_0@b@      //   25: iconst_0@b@      //   26: putfield 2	org/springframework/util/ConcurrentReferenceHashMap$Segment:count	I@b@      //   29: aload_0@b@      //   30: invokevirtual 26	org/springframework/util/ConcurrentReferenceHashMap$Segment:unlock	()V@b@      //   33: goto +10 -> 43@b@      //   36: astore_1@b@      //   37: aload_0@b@      //   38: invokevirtual 26	org/springframework/util/ConcurrentReferenceHashMap$Segment:unlock	()V@b@      //   41: aload_1@b@      //   42: athrow@b@      //   43: return@b@      //@b@      // Exception table:@b@      //   from	to	target	type@b@      //   12	29	36	finally } @b@    protected final void restructureIfNecessary() { boolean needsResize = (this.count > 0) && (this.count >= this.resizeThreshold);@b@      ConcurrentReferenceHashMap.Reference reference = this.referenceManager.pollForPurge();@b@      if ((reference != null) || ((needsResize) && (allowResize))) {@b@        lock();@b@        try {@b@          int countAfterRestructure = this.count;@b@@b@          Set toPurge = Collections.emptySet();@b@          if (reference != null) {@b@            toPurge = new HashSet();@b@            while (reference != null) {@b@              toPurge.add(reference);@b@              reference = this.referenceManager.pollForPurge();@b@            }@b@          }@b@          countAfterRestructure -= toPurge.size();@b@@b@          needsResize = (countAfterRestructure > 0) && (countAfterRestructure >= this.resizeThreshold);@b@          boolean resizing = false;@b@          int restructureSize = this.references.length;@b@          if ((allowResize) && (needsResize) && (restructureSize < 1073741824)) {@b@            restructureSize <<= 1;@b@            resizing = true;@b@          }@b@@b@          ConcurrentReferenceHashMap.Reference[] restructured = (resizing) ? createReferenceArray(restructureSize) : this.references;@b@@b@          for (int i = 0; i < this.references.length; ++i) {@b@            reference = this.references[i];@b@            if (!(resizing))@b@              restructured[i] = null;@b@@b@            while (reference != null) {@b@              if ((!(toPurge.contains(reference))) && (reference.get() != null)) {@b@                int index = getIndex(reference.getHash(), restructured);@b@                restructured[index] = this.referenceManager.createReference(reference@b@                  .get(), reference.getHash(), restructured[index]);@b@              }@b@@b@              reference = reference.getNext();@b@            }@b@@b@          }@b@@b@          if (resizing)@b@            setReferences(restructured);@b@@b@          this.count = Math.max(countAfterRestructure, 0);@b@        }@b@        finally {@b@          unlock();@b@        }@b@      }@b@    }@b@@b@    private ConcurrentReferenceHashMap.Reference<K, V> findInChain(, Object key, int hash) {@b@      while (reference != null) {@b@        if (reference.getHash() == hash) {@b@          ConcurrentReferenceHashMap.Entry entry = reference.get();@b@          if (entry != null) {@b@            Object entryKey = entry.getKey();@b@            if ((entryKey == key) || (entryKey.equals(key)))@b@              return reference;@b@          }@b@        }@b@@b@        reference = reference.getNext();@b@      }@b@      return null;@b@    }@b@@b@    private ConcurrentReferenceHashMap.Reference<K, V>[] createReferenceArray()@b@    {@b@      return ((ConcurrentReferenceHashMap.Reference[])(ConcurrentReferenceHashMap.Reference[])Array.newInstance(ConcurrentReferenceHashMap.Reference.class, size));@b@    }@b@@b@    private int getIndex(, ConcurrentReferenceHashMap.Reference<K, V>[] references) {@b@      return (hash & references.length - 1);@b@    }@b@@b@    private void setReferences()@b@    {@b@      this.references = references;@b@      this.resizeThreshold = (int)(references.length * this.this$0.getLoadFactor());@b@    }@b@@b@    public final int getSize()@b@    {@b@      return this.references.length;@b@    }@b@@b@    public final int getCount()@b@    {@b@      return this.count;@b@    }@b@  }@b@@b@  public static enum ReferenceType@b@  {@b@    SOFT, WEAK;@b@  }@b@}