为啥要使用WeakCache作为动态代理的缓存,我在网上看到了一个文章,What is the use case of WeakCache in Java? [closed], 可以将里面的图片对象 类比 生成的代理类(都要占用较大的内存),也不知正确与否(JVM早日把你干掉!!!) 我认为的原因是,
// 弱引用被回收时,将被添加到这个引用队列中
private final ReferenceQueue refQueue
= new ReferenceQueue<>();
// the key type is Object for supporting null key
private final ConcurrentMap
/**
* a cache of proxy classes
*/
private static final WeakCache[], Class>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
private final class Factory implements Supplier {
private final K key;
private final P parameter;
private final Object subKey;
private final ConcurrentMap> valuesMap;
Factory(K key, P parameter, Object subKey,
ConcurrentMap> valuesMap) {
this.key = key;
this.parameter = parameter;
this.subKey = subKey;
this.valuesMap = valuesMap;
}
@Override
public synchronized V get() { // serialize access
// re-check
Supplier supplier = valuesMap.get(subKey);
if (supplier != this) {
// 在我们等待时发生了改变:
// 1. 被一个CacheValue替换了
// 2. were removed because of failure
// 此时,就返回null, 让WeakCache.get 继续循环
return null;
}
// else still us (supplier == this)
// create new value
V value = null;
try {
// !! 此时的valueFactory就是ProxyClassFactory; 这里会去生成代理类
value = Objects.requireNonNull(valueFactory.apply(key, parameter));
} finally {
if (value == null) { // remove us on failure
valuesMap.remove(subKey, this);
}
}
// the only path to reach here is with non-null value
assert value != null;
// wrap value with CacheValue (WeakReference)
CacheValue cacheValue = new CacheValue<>(value);
// 将cacheValue保存起来
reverseMap.put(cacheValue, Boolean.TRUE);
// 用cacheValue替换原有的值
// try replacing us with CacheValue (this should always succeed)
if (!valuesMap.replace(subKey, this, cacheValue)) {
throw new AssertionError("Should not reach here");
}
// successfully replaced us with new CacheValue -> return the value
// wrapped by it
return value;
}
}
private static final class CacheValue
extends WeakReference implements Value
{
private final int hash;
CacheValue(V value) {
// 点super进去看看,你就会知道了!!!
super(value);
this.hash = System.identityHashCode(value); // compare by identity
}
...
}
package spark.examples.scala.grammars.caseclasses
object CaseClass_Test00 {
def simpleMatch(arg: Any) = arg match {
case v: Int => "This is an Int"
case v: (Int, String)