8169425: Values computed by a ClassValue should not strongly reference the ClassValue (original) (raw)
Peter Levart peter.levart at gmail.com
Wed Nov 9 13:15:58 UTC 2016
- Previous message: 8169425: Values computed by a ClassValue should not strongly reference the ClassValue
- Next message: 8169425: Values computed by a ClassValue should not strongly reference the ClassValue
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Hi Paul,
What do you think of introducing a static factory method in ClassValue in addition to your @implNotes. The method would go like this (similar to ThreadLocal.withInitial()):
public abstract class ClassValue {
/**
* Creates a {@code ClassValue} instance which uses given {@code
factory} * function for computing values associated with classes passed as arguments * to {@link #get} method. The given {@code factory} function will only be * weakly reachable * from the created ClassValue instance, so one must ensure that is is not Garbage * Collected at least until the returned ClassValue is not used any more. *
* Attempts to use created ClassValue instance to lazily calculate another * associated value after the given factory function is GCed will result in * {@link IllegalStateException} being thrown from the {@link #get} method. * * @param factory the function to be used to produce values associated with * passed-in classes and created ClassValue instance * @param the type of values associated with created ClassValue instance * @return new instance of ClassValue, weakly referencing given factory function. * @since 9 */ public static ClassValue withWeakFactory( Function, T> factory) { WeakReference<Function, T>> factoryRef = new WeakReference<>(factory);
return new ClassValue<T>() {
@Override
protected T computeValue(Class<?> type) {
Function<? super Class<?>, T> factory = factoryRef.get();
if (factory == null) {
throw new IllegalStateException(
"The value factory function has already been
GC(ed)."); } return factory.apply(type); } }; }
@implNotes could point to this method with an example...
Regards, Peter
On 11/09/2016 01:49 PM, Peter Levart wrote:
Or, better yet, using value factory Function instead of Supplier:
public class WeakFactoryClassValue extends ClassValue { private final WeakReference<Function, ? extends T>> factoryRef; public WeakFactoryClassValue(Function, ? extends T> factory) { factoryRef = new WeakReference<>(factory); } @Override protected T computeValue(Class<?> type) { Function, ? 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 VALUEFACTORY stay at least until MyApp class is alive private static final Function<Class<?>, Object> VALUEFACTORY = clazz -> MyApp.CV; public static final ClassValue CV = new WeakFactoryClassValue<>(VALUEFACTORY); 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 VALUEFACTORY 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 extends ClassValue { > private final WeakReference<Supplier> supplierRef; > > public WeakSupplierClassValue(Supplier supplier) { supplierRef = > new WeakReference<>(supplier); } > > @Override protected T computeValue(Class<?> type) { Supplier > 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 CVSUPPLIER stay at least until MyApp > class is alive private static final Supplier CVSUPPLIER = () > -> MyApp.CV; > > public static final ClassValue CV = new > WeakSupplierClassValue<>(CVSUPPLIER); > > 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 > CVSUPPLIER is only weakly reachable CV.get(Object.class); } } > > > Regards, Peter
- Previous message: 8169425: Values computed by a ClassValue should not strongly reference the ClassValue
- Next message: 8169425: Values computed by a ClassValue should not strongly reference the ClassValue
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]