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