package org.jruby.util.collections;
import java.lang.ref.WeakReference;
import java.util.LinkedList;
import java.util.List;
A proxy cache that uses Java 7's ClassValue.
/**
* A proxy cache that uses Java 7's ClassValue.
*/
final class Java7ClassValue<T> extends ClassValue<T> {
public Java7ClassValue(ClassValueCalculator<T> calculator) {
super(calculator);
}
public T get(Class<?> cls) {
// We don't check for null on the WeakReference since the
// value is strongly referenced by proxy's list
return proxy.get(cls).get();
}
// If we put any objects that reference an org.jruby.Ruby runtime
// (like RubyClass instances) in here we run into a circular
// reference situation that GC isn't handling where they will
// always be strongly referenced and never garbage collected. We
// break that by holding the computed values with a WeakReference.
// This appears to be a bug in OpenJDK. See jruby/jruby#3228.
private final java.lang.ClassValue<WeakReference<T>> proxy = new java.lang.ClassValue<WeakReference<T>>() {
// Strongly reference all computed values so they don't get
// garbage collected until this Java7ClassValue instance goes
// out of scope
private final List<T> computedValues = new LinkedList<>();
@Override
protected WeakReference<T> computeValue(Class<?> type) {
T value = calculator.computeValue(type);
computedValues.add(value);
return new WeakReference(value);
}
};
}