8169425: Values computed by a ClassValue should not strongly reference the ClassValue
Peter Levart
peter.levart at gmail.com
Wed Nov 9 12:49:11 UTC 2016
Or, better yet, using value factory Function instead of Supplier:
public class WeakFactoryClassValue<T> extends ClassValue<T> {
private final WeakReference<Function<? super Class<?>, ? extends
T>> factoryRef;
public WeakFactoryClassValue(Function<? super Class<?>, ? extends
T> factory) {
factoryRef = new WeakReference<>(factory);
}
@Override
protected T computeValue(Class<?> type) {
Function<? super Class<?>, ? extends T> factory = factoryRef.get();
if (factory == null) {
throw new IllegalStateException("Value factory function has
already been GCed");
}
return factory.apply(type);
}
}
The example would then read:
public class MyApp {
// make VALUE_FACTORY stay at least until MyApp class is alive
private static final Function<Class<?>, Object> VALUE_FACTORY =
clazz -> MyApp.CV;
public static final ClassValue<Object> CV =
new WeakFactoryClassValue<>(VALUE_FACTORY);
public static void main(String[] args) {
// this is OK
CV.get(MyApp.class);
// even this is OK, it makes CV reachable from Object.class,
// but VALUE_FACTORY is only weakly reachable
CV.get(Object.class);
}
}
Regards, Peter
On 11/09/2016 01:31 PM, Peter Levart wrote:
> The above situation could be prevented by a special concrete > ClassValue implementation, provided by the platform (loaded by >
bootstrap CL): > > public class WeakSupplierClassValue<T> extends
ClassValue<T> { > private final WeakReference<Supplier<T>> supplierRef;
> > public WeakSupplierClassValue(Supplier<T> supplier) { supplierRef =
> new WeakReference<>(supplier); } > > @Override protected T
computeValue(Class<?> type) { Supplier<T> > supplier =
supplierRef.get(); if (supplier == null) { throw new >
IllegalStateException("Supplier has already been GCed"); } return >
supplier.get(); } } > > > ...with such utility class, one could rewrite
above example to: > > public class MyApp { // make CV_SUPPLIER stay at
least until MyApp > class is alive private static final Supplier<Object>
CV_SUPPLIER = () > -> MyApp.CV; > > public static final
ClassValue<Object> CV = new > WeakSupplierClassValue<>(CV_SUPPLIER); > >
public static void main(String[] args) { // this is OK >
CV.get(MyApp.class); > > // even this is OK, it makes CV reachable from
Object.class, // but > CV_SUPPLIER is only weakly reachable
CV.get(Object.class); } } > > > Regards, Peter
More information about the core-libs-dev
mailing list