// Maps Class instances to values of type T. Under memory pressure, the // mapping is released (under soft references GC policy) and would be // recomputed the next time it is queried. The mapping is bound to the // lifetime of the class: when the class is unloaded, the mapping is // removed too. abstractclass ClassCache<T> {
privatestaticclass CacheRef<T> extends SoftReference<T> { privatefinalClass<?> type; private T strongReferent;
protected ClassCache() {
queue = new ReferenceQueue<>();
map = new ClassValue<>() {
@Override protected CacheRef<T> computeValue(Class<?> type) {
T v = ClassCache.this.computeValue(type);
Objects.requireNonNull(v); returnnew CacheRef<>(v, queue, type);
}
};
}
T get(Class<?> cl) { while (true) {
processQueue();
CacheRef<T> ref = map.get(cl);
// Case 1: A recently created CacheRef. // We might still have strong referent, and can return it. // This guarantees progress for at least one thread on every CacheRef. // Clear the strong referent before returning to make the cache soft.
T strongVal = ref.getStrong(); if (strongVal != null) {
ref.clearStrong(); return strongVal;
}
// Case 2: Older or recently cleared CacheRef. // Check if its soft referent is still available, and return it.
T val = ref.get(); if (val != null) { return val;
}
// Case 3: The reference was cleared. // Clear the mapping and retry.
map.remove(cl);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.