JDK1.8源码学习--lang包(ClassValue)

JDK1.8源码学习--lang包(ClassValue),第1张

JDK1.8源码学习--lang包(ClassValue) 前言


月是一轮明镜,晶莹剔透,代表着一张白纸(啥也不懂)

央是一片海洋,海乃百川,代表着一块海绵(吸纳万物)

泽是一柄利剑,千锤百炼,代表着千百锤炼(输入输出)

月央泽,学习的一种过程,从白纸->吸收各种知识->不断输入输出变成自己的内容

希望大家一起坚持这个过程,也同样希望大家最终都能从零到零,把知识从薄变厚,再由厚变薄!
 

一.ClassValue的作用:

         直接看源码注释(我的翻译可能不太准,如果道友们有更棒的理解,可以留言或者私信)

 
二.成员变量:   
 
    //所有 Class 实例使用的初始、单元素、空缓存。绝对不能填满
    private static final Entry[] EMPTY_CACHE = { null };


    //用于访问 Class.classValueMap.cacheArray 的内部哈希码。
    final int hashCodeForCache = nextHashCode.getAndAdd(HASH_INCREMENT) & HASH_MASK;


    //hashCodeForCache 的值流。请参阅 ThreadLocal 中的类似结构
    private static final AtomicInteger nextHashCode = new AtomicInteger();


    //适用于 2 的幂表。请参阅 ThreadLocal 中的类似结构
    private static final int HASH_INCREMENT = 0x61c88647;


    //将哈希码屏蔽为正数但不要太大,以防止回绕。
    static final int HASH_MASK = (-1 >>> 2);


    
    final Identity identity = new Identity();

 //避免死锁的私有对象
    private static final Object CRITICAL_SECTION = new Object();

//判断当前对象的版本
 private volatile Version version = new Version<>(this);
三.内部类: 

                Identity

    static class Identity {
    }

                Version

 static class Version {
        private final ClassValue classValue;
        private final Entry promise = new Entry<>(this);
        Version(ClassValue classValue) { this.classValue = classValue; }
        ClassValue classValue() { return classValue; }
        Entry promise() { return promise; }
        boolean isLive() { return classValue.version() == this; }
    }

                Entry

    
    static class Entry extends WeakReference> {
        //通常是 T 型,但有时 (Entry)this
        final Object value;  // usually of type T, but sometimes (Entry)this
        Entry(Version version, T value) {
            super(version);
            //对于常规条目,值的类型为 T
            this.value = value;  // for a regular entry, value is of type T
        }
        private void assertNotPromise() { assert(!isPromise()); }
        
        //promise状态
        Entry(Version version) {
            super(version);
            this.value = this;  // for a promise, value is not of type T, but Entry!
        }
        
        //取值。此条目不能是Promise
        @SuppressWarnings("unchecked")  // if !isPromise, type is T
        T value() { assertNotPromise(); return (T) value; }
        boolean isPromise() { return value == this; }
        Version version() { return get(); }
        ClassValue classValueOrNull() {
            Version v = version();
            return (v == null) ? null : v.classValue();
        }
        boolean isLive() {
            Version v = version();
            if (v == null)  return false;
            if (v.isLive())  return true;
            clear();
            return false;
        }
        Entry refreshVersion(Version v2) {
            assertNotPromise();
            @SuppressWarnings("unchecked")  // if !isPromise, type is T
            Entry e2 = new Entry<>(v2, (T) value);
            clear();
            // value = null -- caller must drop
            return e2;
        }
        //dead状态
        static final Entry DEAD_ENTRY = new Entry<>(null, null);
    }

                ClassValueMap


    
    static class ClassValueMap extends WeakHashMap> {
        private final Class type;
        private Entry[] cacheArray;
        private int cacheLoad, cacheLoadLimit;

        
        private static final int INITIAL_ENTRIES = 32;

        
        ClassValueMap(Class type) {
            this.type = type;
            sizeCache(INITIAL_ENTRIES);
        }

        Entry[] getCache() { return cacheArray; }

    
        //发起查询。如果还没有值,则存储promise(占位符)
        synchronized
         Entry startEntry(ClassValue classValue) {
            @SuppressWarnings("unchecked")  // one map has entries for all value types 
            Entry e = (Entry) get(classValue.identity);
            Version v = classValue.version();
            if (e == null) {
                e = v.promise();
                //promise的存在意味着 v 的值正在等待。最终,finishEntry 将覆盖promise
                put(classValue.identity, e);
                // Note that the promise is never entered into the cache!
                //请注意,promise永远不会进入缓存
                return e;
            } else if (e.isPromise()) {
                // Somebody else has asked the same question.
                // Let the races begin!
                if (e.version() != v) {
                    e = v.promise();
                    put(classValue.identity, e);
                }
                return e;
            } else {
                // there is already a completed entry here; report it
                //这里已经有一个完整的条目;举报
                if (e.version() != v) {
                    //这里有一个陈旧但有效的条目;让它再次新鲜。
                    // 一旦一个条目在哈希表中,我们就不关心它的版本是什么
                    e = e.refreshVersion(v);
                    put(classValue.identity, e);
                }
                // Add to the cache, to enable the fast path, next time.
                //添加到缓存中,下次以启用快速路径,
                checkCacheLoad();
                addToCache(classValue, e);
                return e;
            }
        }
        synchronized
         Entry finishEntry(ClassValue classValue, Entry e) {
            @SuppressWarnings("unchecked")  // one map has entries for all value types 
            Entry e0 = (Entry) get(classValue.identity);
            if (e == e0) {
                // We can get here during exception processing, unwinding from computevalue.
                assert(e.isPromise());
                remove(classValue.identity);
                return null;
            } else if (e0 != null && e0.isPromise() && e0.version() == e.version()) {
                // If e0 matches the intended entry, there has not been a remove call
                // between the previous startEntry and now.  So now overwrite e0.
                Version v = classValue.version();
                if (e.version() != v)
                    e = e.refreshVersion(v);
                put(classValue.identity, e);
                // Add to the cache, to enable the fast path, next time.
                checkCacheLoad();
                addToCache(classValue, e);
                return e;
            } else {
                // Some sort of mismatch; caller must try again.
                return null;
            }
        }

        
        synchronized
        void removeEntry(ClassValue classValue) {
            Entry e = remove(classValue.identity);
            if (e == null) {
                // Uninitialized, and no pending calls to computevalue.  No change.
            } else if (e.isPromise()) {
                // State is uninitialized, with a pending call to finishEntry.
                // Since remove is a no-op in such a state, keep the promise
                // by putting it back into the map.
                put(classValue.identity, e);
            } else {
                // In an initialized state.  Bump forward, and de-initialize.
                classValue.bumpVersion();
                // Make all cache elements for this guy go stale.
                removeStaleEntries(classValue);
            }
        }

        
        synchronized
         void changeEntry(ClassValue classValue, T value) {
            @SuppressWarnings("unchecked")  // one map has entries for all value types 
            Entry e0 = (Entry) get(classValue.identity);
            Version version = classValue.version();
            if (e0 != null) {
                if (e0.version() == version && e0.value() == value)
                    // no value change => no version change needed
                    return;
                classValue.bumpVersion();
                removeStaleEntries(classValue);
            }
            Entry e = makeEntry(version, value);
            put(classValue.identity, e);
            // Add to the cache, to enable the fast path, next time.
            checkCacheLoad();
            addToCache(classValue, e);
        }


        static Entry loadFromCache(Entry[] cache, int i) {
            // non-racing cache.length : constant
            // racing cache[i & (mask)] : null <=> Entry
            return cache[i & (cache.length-1)];
            // invariant:  returned value is null or well-constructed (ready to match)
        }

        
        static  Entry probeHomeLocation(Entry[] cache, ClassValue classValue) {
            return classValue.castEntry(loadFromCache(cache, classValue.hashCodeForCache));
        }

        
        static  Entry probeBackupLocations(Entry[] cache, ClassValue classValue) {
            if (PROBE_LIMIT <= 0)  return null;
            // Probe the cache carefully, in a range of slots.
            int mask = (cache.length-1);
            int home = (classValue.hashCodeForCache & mask);
            Entry e2 = cache[home];  // victim, if we find the real guy
            if (e2 == null) {
                return null;   // if nobody is at home, no need to search nearby
            }
            // assume !classValue.match(e2), but do not assert, because of races
            int pos2 = -1;
            for (int i = home + 1; i < home + PROBE_LIMIT; i++) {
                Entry e = cache[i & mask];
                if (e == null) {
                    break;   // only search within non-null runs
                }
                if (classValue.match(e)) {
                    // relocate colliding entry e2 (from cache[home]) to first empty slot
                    cache[home] = e;
                    if (pos2 >= 0) {
                        cache[i & mask] = Entry.DEAD_ENTRY;
                    } else {
                        pos2 = i;
                    }
                    cache[pos2 & mask] = ((entryDislocation(cache, pos2, e2) < PROBE_LIMIT)
                                          ? e2                  // put e2 here if it fits
                                          : Entry.DEAD_ENTRY);
                    return classValue.castEntry(e);
                }
                // Remember first empty slot, if any:
                if (!e.isLive() && pos2 < 0)  pos2 = i;
            }
            return null;
        }

        
        //e 离位多远?
        private static int entryDislocation(Entry[] cache, int pos, Entry e) {
            ClassValue cv = e.classValueOrNull();
            if (cv == null)  return 0;  // entry is not live!
            int mask = (cache.length-1);
            return (pos - cv.hashCodeForCache) & mask;
        }

        private void sizeCache(int length) {
            assert((length & (length-1)) == 0);  // must be power of 2
            cacheLoad = 0;
            cacheLoadLimit = (int) ((double) length * CACHE_LOAD_LIMIT / 100);
            cacheArray = new Entry[length];
        }

        
        //如果可能,请确保缓存负载保持在其限制以下
        private void checkCacheLoad() {
            if (cacheLoad >= cacheLoadLimit) {
                reduceCacheLoad();
            }
        }
        private void reduceCacheLoad() {
            removeStaleEntries();
            if (cacheLoad < cacheLoadLimit)
                return;  // win
            Entry[] oldCache = getCache();
            if (oldCache.length > HASH_MASK)
                return;  // lose
            sizeCache(oldCache.length * 2);
            for (Entry e : oldCache) {
                if (e != null && e.isLive()) {
                    addToCache(e);
                }
            }
        }

        
        private void removeStaleEntries(Entry[] cache, int begin, int count) {
            if (PROBE_LIMIT <= 0)  return;
            int mask = (cache.length-1);
            int removed = 0;
            for (int i = begin; i < begin + count; i++) {
                Entry e = cache[i & mask];
                if (e == null || e.isLive())
                    continue;  // skip null and live entries
                Entry replacement = null;
                if (PROBE_LIMIT > 1) {
                    // avoid breaking up a non-null run
                    //避免中断非空运行
                    replacement = findReplacement(cache, i);
                }
                cache[i & mask] = replacement;
                if (replacement == null)  removed += 1;
            }
            cacheLoad = Math.max(0, cacheLoad - removed);
        }

        
        private Entry findReplacement(Entry[] cache, int home1) {
            Entry replacement = null;
            int haveReplacement = -1, replacementPos = 0;
            int mask = (cache.length-1);
            for (int i2 = home1 + 1; i2 < home1 + PROBE_LIMIT; i2++) {
                Entry e2 = cache[i2 & mask];
                if (e2 == null)  break;  // End of non-null run.
                if (!e2.isLive())  continue;  // Doomed anyway.
                int dis2 = entryDislocation(cache, i2, e2);
                if (dis2 == 0)  continue;  // e2 already optimally placed
                int home2 = i2 - dis2;
                if (home2 <= home1) {
                    // e2 can replace entry at cache[home1]
                    if (home2 == home1) {
                        // Put e2 exactly where he belongs.
                        haveReplacement = 1;
                        replacementPos = i2;
                        replacement = e2;
                    } else if (haveReplacement <= 0) {
                        haveReplacement = 0;
                        replacementPos = i2;
                        replacement = e2;
                    }
                    // And keep going, so we can favor larger dislocations.
                }
            }
            if (haveReplacement >= 0) {
                if (cache[(replacementPos+1) & mask] != null) {
                    // Be conservative, to avoid breaking up a non-null run.
                    cache[replacementPos & mask] = (Entry) Entry.DEAD_ENTRY;
                } else {
                    cache[replacementPos & mask] = null;
                    cacheLoad -= 1;
                }
            }
            return replacement;
        }


        //删除 classValue 附近范围内的陈旧条目
        private void removeStaleEntries(ClassValue classValue) {
            removeStaleEntries(getCache(), classValue.hashCodeForCache, PROBE_LIMIT);
        }

        //删除所有陈旧条目,无处不在
        private void removeStaleEntries() {
            Entry[] cache = getCache();
            removeStaleEntries(cache, 0, cache.length + PROBE_LIMIT - 1);
        }

        //将给定条目添加到缓存中,在其主位置,除非它已过期
        private  void addToCache(Entry e) {
            ClassValue classValue = e.classValueOrNull();
            if (classValue != null)
                addToCache(classValue, e);
        }

        //将给定的条目添加到缓存中,在其主位置
        private  void addToCache(ClassValue classValue, Entry e) {
            if (PROBE_LIMIT <= 0)  return;  // do not fill cache
            // Add e to the cache.
            Entry[] cache = getCache();
            int mask = (cache.length-1);
            int home = classValue.hashCodeForCache & mask;
            Entry e2 = placeInCache(cache, home, e, false);
            if (e2 == null)  return;  // done
            if (PROBE_LIMIT > 1) {
                // try to move e2 somewhere else in his probe range
                int dis2 = entryDislocation(cache, home, e2);
                int home2 = home - dis2;
                for (int i2 = home2; i2 < home2 + PROBE_LIMIT; i2++) {
                    if (placeInCache(cache, i2 & mask, e2, true) == null) {
                        return;
                    }
                }
            }
            // Note:  At this point, e2 is just dropped from the cache.
        }

        
        private Entry placeInCache(Entry[] cache, int pos, Entry e, boolean gently) {
            Entry e2 = overwrittenEntry(cache[pos]);
            if (gently && e2 != null) {
                // do not overwrite a live entry
                return e;
            } else {
                cache[pos] = e;
                return e2;
            }
        }

        
        private  Entry overwrittenEntry(Entry e2) {
            if (e2 == null)  cacheLoad += 1;
            else if (e2.isLive())  return e2;
            return null;
        }

        
        //调整大小前缓存的加载百分比
        private static final int CACHE_LOAD_LIMIT = 67;  // 0..100
        
        //尝试的最大探测数
        private static final int PROBE_LIMIT      =  6;       // 1..
    }
四.构造方法:
 
    protected ClassValue() {
    }
五.内部方法: 

                computevalue

   
    protected abstract T computevalue(Class type);

                get()

    
    public T get(Class type) {

        Entry[] cache;
        Entry e = probeHomeLocation(cache = getCacheCarefully(type), this);

        //当前值 <=> 来自当前缓存或陈旧缓存的陈旧值
        //e 为 null 或具有可读 Entry.version 和 Entry.value 的条目
        if (match(e))
            return e.value();
        //快速路径可能因以下任何原因而失败: 
        // 1. 尚未计算任何条目 
        // 2. 哈希码冲突(减少 mod cache.length 之前或之后) 
        // 3. 条目已被删除(在此类型或其他类型上) 
        // 4 . GC 以某种方式设法删除了 e.version 并清除了引用
        return getFromBackup(cache, type);
    }

                remove()

  
    public void remove(Class type) {
        ClassValueMap map = getMap(type);
        map.removeEntry(this);
    }

                match

    //检查 e 是否为非空、是否与此 ClassValue 匹配且是否有效
    boolean match(Entry e) {
        return (e != null && e.get() == this.version);

    }
六.总结:

        mark一下,看未来这东西有啥用....

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5638484.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存